blob: 9c5f4416d1bbf5a754f1c8d5ff426070e10f9d96 [file] [log] [blame]
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001/*
2 An implementation of Text I/O as defined by PEP 3116 - "New I/O"
Antoine Pitrou24f36292009-03-28 22:16:42 +00003
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00004 Classes defined here: TextIOBase, IncrementalNewlineDecoder, TextIOWrapper.
Antoine Pitrou24f36292009-03-28 22:16:42 +00005
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00006 Written by Amaury Forgeot d'Arc and Antoine Pitrou
7*/
8
9#define PY_SSIZE_T_CLEAN
10#include "Python.h"
11#include "structmember.h"
12#include "_iomodule.h"
13
14/* TextIOBase */
15
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000016PyDoc_STRVAR(textiobase_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000017 "Base class for text I/O.\n"
18 "\n"
19 "This class provides a character and line based interface to stream\n"
20 "I/O. There is no readinto method because Python's character strings\n"
21 "are immutable. There is no public constructor.\n"
22 );
23
24static PyObject *
25_unsupported(const char *message)
26{
27 PyErr_SetString(IO_STATE->unsupported_operation, message);
28 return NULL;
29}
30
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000031PyDoc_STRVAR(textiobase_detach_doc,
Benjamin Petersond2e0c792009-05-01 20:40:59 +000032 "Separate the underlying buffer from the TextIOBase and return it.\n"
33 "\n"
34 "After the underlying buffer has been detached, the TextIO is in an\n"
35 "unusable state.\n"
36 );
37
38static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000039textiobase_detach(PyObject *self)
Benjamin Petersond2e0c792009-05-01 20:40:59 +000040{
41 return _unsupported("detach");
42}
43
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000044PyDoc_STRVAR(textiobase_read_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000045 "Read at most n characters from stream.\n"
46 "\n"
47 "Read from underlying buffer until we have n characters or we hit EOF.\n"
48 "If n is negative or omitted, read until EOF.\n"
49 );
50
51static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000052textiobase_read(PyObject *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000053{
54 return _unsupported("read");
55}
56
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000057PyDoc_STRVAR(textiobase_readline_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000058 "Read until newline or EOF.\n"
59 "\n"
60 "Returns an empty string if EOF is hit immediately.\n"
61 );
62
63static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000064textiobase_readline(PyObject *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000065{
66 return _unsupported("readline");
67}
68
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000069PyDoc_STRVAR(textiobase_write_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000070 "Write string to stream.\n"
71 "Returns the number of characters written (which is always equal to\n"
72 "the length of the string).\n"
73 );
74
75static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000076textiobase_write(PyObject *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000077{
78 return _unsupported("write");
79}
80
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000081PyDoc_STRVAR(textiobase_encoding_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000082 "Encoding of the text stream.\n"
83 "\n"
84 "Subclasses should override.\n"
85 );
86
87static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000088textiobase_encoding_get(PyObject *self, void *context)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000089{
90 Py_RETURN_NONE;
91}
92
Benjamin Peterson680bf1a2009-06-12 02:07:12 +000093PyDoc_STRVAR(textiobase_newlines_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +000094 "Line endings translated so far.\n"
95 "\n"
96 "Only line endings translated during reading are considered.\n"
97 "\n"
98 "Subclasses should override.\n"
99 );
100
101static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000102textiobase_newlines_get(PyObject *self, void *context)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000103{
104 Py_RETURN_NONE;
105}
106
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000107PyDoc_STRVAR(textiobase_errors_doc,
Benjamin Peterson0926ad12009-06-06 18:02:12 +0000108 "The error setting of the decoder or encoder.\n"
109 "\n"
110 "Subclasses should override.\n"
111 );
112
113static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000114textiobase_errors_get(PyObject *self, void *context)
Benjamin Peterson0926ad12009-06-06 18:02:12 +0000115{
116 Py_RETURN_NONE;
117}
118
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000119
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000120static PyMethodDef textiobase_methods[] = {
121 {"detach", (PyCFunction)textiobase_detach, METH_NOARGS, textiobase_detach_doc},
122 {"read", textiobase_read, METH_VARARGS, textiobase_read_doc},
123 {"readline", textiobase_readline, METH_VARARGS, textiobase_readline_doc},
124 {"write", textiobase_write, METH_VARARGS, textiobase_write_doc},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000125 {NULL, NULL}
126};
127
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000128static PyGetSetDef textiobase_getset[] = {
129 {"encoding", (getter)textiobase_encoding_get, NULL, textiobase_encoding_doc},
130 {"newlines", (getter)textiobase_newlines_get, NULL, textiobase_newlines_doc},
131 {"errors", (getter)textiobase_errors_get, NULL, textiobase_errors_doc},
Benjamin Peterson1fea3212009-04-19 03:15:20 +0000132 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000133};
134
135PyTypeObject PyTextIOBase_Type = {
136 PyVarObject_HEAD_INIT(NULL, 0)
137 "_io._TextIOBase", /*tp_name*/
138 0, /*tp_basicsize*/
139 0, /*tp_itemsize*/
140 0, /*tp_dealloc*/
141 0, /*tp_print*/
142 0, /*tp_getattr*/
143 0, /*tp_setattr*/
144 0, /*tp_compare */
145 0, /*tp_repr*/
146 0, /*tp_as_number*/
147 0, /*tp_as_sequence*/
148 0, /*tp_as_mapping*/
149 0, /*tp_hash */
150 0, /*tp_call*/
151 0, /*tp_str*/
152 0, /*tp_getattro*/
153 0, /*tp_setattro*/
154 0, /*tp_as_buffer*/
155 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000156 textiobase_doc, /* tp_doc */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000157 0, /* tp_traverse */
158 0, /* tp_clear */
159 0, /* tp_richcompare */
160 0, /* tp_weaklistoffset */
161 0, /* tp_iter */
162 0, /* tp_iternext */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000163 textiobase_methods, /* tp_methods */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000164 0, /* tp_members */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000165 textiobase_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000166 &PyIOBase_Type, /* tp_base */
167 0, /* tp_dict */
168 0, /* tp_descr_get */
169 0, /* tp_descr_set */
170 0, /* tp_dictoffset */
171 0, /* tp_init */
172 0, /* tp_alloc */
173 0, /* tp_new */
174};
175
176
177/* IncrementalNewlineDecoder */
178
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000179PyDoc_STRVAR(incrementalnewlinedecoder_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000180 "Codec used when reading a file in universal newlines mode. It wraps\n"
181 "another incremental decoder, translating \\r\\n and \\r into \\n. It also\n"
182 "records the types of newlines encountered. When used with\n"
183 "translate=False, it ensures that the newline sequence is returned in\n"
184 "one piece. When used with decoder=None, it expects unicode strings as\n"
185 "decode input and translates newlines without first invoking an external\n"
186 "decoder.\n"
187 );
188
189typedef struct {
190 PyObject_HEAD
191 PyObject *decoder;
192 PyObject *errors;
Antoine Pitrouca767bd2009-09-21 21:37:02 +0000193 signed int pendingcr: 1;
194 signed int translate: 1;
195 unsigned int seennl: 3;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000196} nldecoder_object;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000197
198static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000199incrementalnewlinedecoder_init(nldecoder_object *self,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000200 PyObject *args, PyObject *kwds)
201{
202 PyObject *decoder;
203 int translate;
204 PyObject *errors = NULL;
205 char *kwlist[] = {"decoder", "translate", "errors", NULL};
206
207 if (!PyArg_ParseTupleAndKeywords(args, kwds, "Oi|O:IncrementalNewlineDecoder",
208 kwlist, &decoder, &translate, &errors))
209 return -1;
210
211 self->decoder = decoder;
212 Py_INCREF(decoder);
213
214 if (errors == NULL) {
215 self->errors = PyUnicode_FromString("strict");
216 if (self->errors == NULL)
217 return -1;
218 }
219 else {
220 Py_INCREF(errors);
221 self->errors = errors;
222 }
223
224 self->translate = translate;
225 self->seennl = 0;
226 self->pendingcr = 0;
227
228 return 0;
229}
230
231static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000232incrementalnewlinedecoder_dealloc(nldecoder_object *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000233{
234 Py_CLEAR(self->decoder);
235 Py_CLEAR(self->errors);
236 Py_TYPE(self)->tp_free((PyObject *)self);
237}
238
239#define SEEN_CR 1
240#define SEEN_LF 2
241#define SEEN_CRLF 4
242#define SEEN_ALL (SEEN_CR | SEEN_LF | SEEN_CRLF)
243
244PyObject *
Antoine Pitrou24f36292009-03-28 22:16:42 +0000245_PyIncrementalNewlineDecoder_decode(PyObject *_self,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000246 PyObject *input, int final)
247{
248 PyObject *output;
249 Py_ssize_t output_len;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000250 nldecoder_object *self = (nldecoder_object *) _self;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000251
252 if (self->decoder == NULL) {
253 PyErr_SetString(PyExc_ValueError,
254 "IncrementalNewlineDecoder.__init__ not called");
255 return NULL;
256 }
257
258 /* decode input (with the eventual \r from a previous pass) */
259 if (self->decoder != Py_None) {
260 output = PyObject_CallMethodObjArgs(self->decoder,
261 _PyIO_str_decode, input, final ? Py_True : Py_False, NULL);
262 }
263 else {
264 output = input;
265 Py_INCREF(output);
266 }
267
268 if (output == NULL)
269 return NULL;
270
271 if (!PyUnicode_Check(output)) {
272 PyErr_SetString(PyExc_TypeError,
273 "decoder should return a string result");
274 goto error;
275 }
276
277 output_len = PyUnicode_GET_SIZE(output);
278 if (self->pendingcr && (final || output_len > 0)) {
279 Py_UNICODE *out;
280 PyObject *modified = PyUnicode_FromUnicode(NULL, output_len + 1);
281 if (modified == NULL)
282 goto error;
283 out = PyUnicode_AS_UNICODE(modified);
284 out[0] = '\r';
285 memcpy(out + 1, PyUnicode_AS_UNICODE(output),
286 output_len * sizeof(Py_UNICODE));
287 Py_DECREF(output);
288 output = modified;
289 self->pendingcr = 0;
290 output_len++;
291 }
292
293 /* retain last \r even when not translating data:
294 * then readline() is sure to get \r\n in one pass
295 */
296 if (!final) {
Antoine Pitrou24f36292009-03-28 22:16:42 +0000297 if (output_len > 0
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000298 && PyUnicode_AS_UNICODE(output)[output_len - 1] == '\r') {
299
300 if (Py_REFCNT(output) == 1) {
301 if (PyUnicode_Resize(&output, output_len - 1) < 0)
302 goto error;
303 }
304 else {
305 PyObject *modified = PyUnicode_FromUnicode(
306 PyUnicode_AS_UNICODE(output),
307 output_len - 1);
308 if (modified == NULL)
309 goto error;
310 Py_DECREF(output);
311 output = modified;
312 }
313 self->pendingcr = 1;
314 }
315 }
316
317 /* Record which newlines are read and do newline translation if desired,
318 all in one pass. */
319 {
320 Py_UNICODE *in_str;
321 Py_ssize_t len;
322 int seennl = self->seennl;
323 int only_lf = 0;
324
325 in_str = PyUnicode_AS_UNICODE(output);
326 len = PyUnicode_GET_SIZE(output);
327
328 if (len == 0)
329 return output;
330
331 /* If, up to now, newlines are consistently \n, do a quick check
332 for the \r *byte* with the libc's optimized memchr.
333 */
334 if (seennl == SEEN_LF || seennl == 0) {
Antoine Pitrou0e941892009-03-06 23:57:20 +0000335 only_lf = (memchr(in_str, '\r', len * sizeof(Py_UNICODE)) == NULL);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000336 }
337
Antoine Pitrou66913e22009-03-06 23:40:56 +0000338 if (only_lf) {
339 /* If not already seen, quick scan for a possible "\n" character.
340 (there's nothing else to be done, even when in translation mode)
341 */
342 if (seennl == 0 &&
343 memchr(in_str, '\n', len * sizeof(Py_UNICODE)) != NULL) {
344 Py_UNICODE *s, *end;
345 s = in_str;
346 end = in_str + len;
347 for (;;) {
348 Py_UNICODE c;
349 /* Fast loop for non-control characters */
350 while (*s > '\n')
351 s++;
352 c = *s++;
353 if (c == '\n') {
354 seennl |= SEEN_LF;
355 break;
356 }
357 if (s > end)
358 break;
359 }
360 }
361 /* Finished: we have scanned for newlines, and none of them
362 need translating */
363 }
364 else if (!self->translate) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000365 Py_UNICODE *s, *end;
Antoine Pitrou66913e22009-03-06 23:40:56 +0000366 /* We have already seen all newline types, no need to scan again */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000367 if (seennl == SEEN_ALL)
368 goto endscan;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000369 s = in_str;
370 end = in_str + len;
371 for (;;) {
372 Py_UNICODE c;
373 /* Fast loop for non-control characters */
374 while (*s > '\r')
375 s++;
376 c = *s++;
377 if (c == '\n')
378 seennl |= SEEN_LF;
379 else if (c == '\r') {
380 if (*s == '\n') {
381 seennl |= SEEN_CRLF;
382 s++;
383 }
384 else
385 seennl |= SEEN_CR;
386 }
387 if (s > end)
388 break;
389 if (seennl == SEEN_ALL)
390 break;
391 }
392 endscan:
393 ;
394 }
Antoine Pitrou66913e22009-03-06 23:40:56 +0000395 else {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000396 PyObject *translated = NULL;
397 Py_UNICODE *out_str;
398 Py_UNICODE *in, *out, *end;
399 if (Py_REFCNT(output) != 1) {
400 /* We could try to optimize this so that we only do a copy
401 when there is something to translate. On the other hand,
402 most decoders should only output non-shared strings, i.e.
403 translation is done in place. */
404 translated = PyUnicode_FromUnicode(NULL, len);
405 if (translated == NULL)
406 goto error;
407 assert(Py_REFCNT(translated) == 1);
408 memcpy(PyUnicode_AS_UNICODE(translated),
409 PyUnicode_AS_UNICODE(output),
410 len * sizeof(Py_UNICODE));
411 }
412 else {
413 translated = output;
414 }
415 out_str = PyUnicode_AS_UNICODE(translated);
416 in = in_str;
417 out = out_str;
418 end = in_str + len;
419 for (;;) {
420 Py_UNICODE c;
421 /* Fast loop for non-control characters */
422 while ((c = *in++) > '\r')
423 *out++ = c;
424 if (c == '\n') {
425 *out++ = c;
426 seennl |= SEEN_LF;
427 continue;
428 }
429 if (c == '\r') {
430 if (*in == '\n') {
431 in++;
432 seennl |= SEEN_CRLF;
433 }
434 else
435 seennl |= SEEN_CR;
436 *out++ = '\n';
437 continue;
438 }
439 if (in > end)
440 break;
441 *out++ = c;
442 }
443 if (translated != output) {
444 Py_DECREF(output);
445 output = translated;
446 }
447 if (out - out_str != len) {
448 if (PyUnicode_Resize(&output, out - out_str) < 0)
449 goto error;
450 }
451 }
452 self->seennl |= seennl;
453 }
454
455 return output;
456
457 error:
458 Py_DECREF(output);
459 return NULL;
460}
461
462static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000463incrementalnewlinedecoder_decode(nldecoder_object *self,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000464 PyObject *args, PyObject *kwds)
465{
466 char *kwlist[] = {"input", "final", NULL};
467 PyObject *input;
468 int final = 0;
469
470 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|i:IncrementalNewlineDecoder",
471 kwlist, &input, &final))
472 return NULL;
473 return _PyIncrementalNewlineDecoder_decode((PyObject *) self, input, final);
474}
475
476static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000477incrementalnewlinedecoder_getstate(nldecoder_object *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000478{
479 PyObject *buffer;
480 unsigned PY_LONG_LONG flag;
481
482 if (self->decoder != Py_None) {
483 PyObject *state = PyObject_CallMethodObjArgs(self->decoder,
484 _PyIO_str_getstate, NULL);
485 if (state == NULL)
486 return NULL;
487 if (!PyArg_Parse(state, "(OK)", &buffer, &flag)) {
488 Py_DECREF(state);
489 return NULL;
490 }
491 Py_INCREF(buffer);
492 Py_DECREF(state);
493 }
494 else {
495 buffer = PyBytes_FromString("");
496 flag = 0;
497 }
498 flag <<= 1;
499 if (self->pendingcr)
500 flag |= 1;
501 return Py_BuildValue("NK", buffer, flag);
502}
503
504static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000505incrementalnewlinedecoder_setstate(nldecoder_object *self, PyObject *state)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000506{
507 PyObject *buffer;
508 unsigned PY_LONG_LONG flag;
509
510 if (!PyArg_Parse(state, "(OK)", &buffer, &flag))
511 return NULL;
512
513 self->pendingcr = (int) flag & 1;
514 flag >>= 1;
515
516 if (self->decoder != Py_None)
517 return PyObject_CallMethod(self->decoder,
518 "setstate", "((OK))", buffer, flag);
519 else
520 Py_RETURN_NONE;
521}
522
523static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000524incrementalnewlinedecoder_reset(nldecoder_object *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000525{
526 self->seennl = 0;
527 self->pendingcr = 0;
528 if (self->decoder != Py_None)
529 return PyObject_CallMethodObjArgs(self->decoder, _PyIO_str_reset, NULL);
530 else
531 Py_RETURN_NONE;
532}
533
534static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000535incrementalnewlinedecoder_newlines_get(nldecoder_object *self, void *context)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000536{
537 switch (self->seennl) {
538 case SEEN_CR:
539 return PyUnicode_FromString("\r");
540 case SEEN_LF:
541 return PyUnicode_FromString("\n");
542 case SEEN_CRLF:
543 return PyUnicode_FromString("\r\n");
544 case SEEN_CR | SEEN_LF:
545 return Py_BuildValue("ss", "\r", "\n");
546 case SEEN_CR | SEEN_CRLF:
547 return Py_BuildValue("ss", "\r", "\r\n");
548 case SEEN_LF | SEEN_CRLF:
549 return Py_BuildValue("ss", "\n", "\r\n");
550 case SEEN_CR | SEEN_LF | SEEN_CRLF:
551 return Py_BuildValue("sss", "\r", "\n", "\r\n");
552 default:
553 Py_RETURN_NONE;
554 }
555
556}
557
558
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000559static PyMethodDef incrementalnewlinedecoder_methods[] = {
560 {"decode", (PyCFunction)incrementalnewlinedecoder_decode, METH_VARARGS|METH_KEYWORDS},
561 {"getstate", (PyCFunction)incrementalnewlinedecoder_getstate, METH_NOARGS},
562 {"setstate", (PyCFunction)incrementalnewlinedecoder_setstate, METH_O},
563 {"reset", (PyCFunction)incrementalnewlinedecoder_reset, METH_NOARGS},
Benjamin Peterson1fea3212009-04-19 03:15:20 +0000564 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000565};
566
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000567static PyGetSetDef incrementalnewlinedecoder_getset[] = {
568 {"newlines", (getter)incrementalnewlinedecoder_newlines_get, NULL, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +0000569 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000570};
571
572PyTypeObject PyIncrementalNewlineDecoder_Type = {
573 PyVarObject_HEAD_INIT(NULL, 0)
574 "_io.IncrementalNewlineDecoder", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000575 sizeof(nldecoder_object), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000576 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000577 (destructor)incrementalnewlinedecoder_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000578 0, /*tp_print*/
579 0, /*tp_getattr*/
580 0, /*tp_setattr*/
581 0, /*tp_compare */
582 0, /*tp_repr*/
583 0, /*tp_as_number*/
584 0, /*tp_as_sequence*/
585 0, /*tp_as_mapping*/
586 0, /*tp_hash */
587 0, /*tp_call*/
588 0, /*tp_str*/
589 0, /*tp_getattro*/
590 0, /*tp_setattro*/
591 0, /*tp_as_buffer*/
592 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000593 incrementalnewlinedecoder_doc, /* tp_doc */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000594 0, /* tp_traverse */
595 0, /* tp_clear */
596 0, /* tp_richcompare */
597 0, /*tp_weaklistoffset*/
598 0, /* tp_iter */
599 0, /* tp_iternext */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000600 incrementalnewlinedecoder_methods, /* tp_methods */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000601 0, /* tp_members */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000602 incrementalnewlinedecoder_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000603 0, /* tp_base */
604 0, /* tp_dict */
605 0, /* tp_descr_get */
606 0, /* tp_descr_set */
607 0, /* tp_dictoffset */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000608 (initproc)incrementalnewlinedecoder_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000609 0, /* tp_alloc */
610 PyType_GenericNew, /* tp_new */
611};
612
613
614/* TextIOWrapper */
615
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000616PyDoc_STRVAR(textiowrapper_doc,
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000617 "Character and line based layer over a BufferedIOBase object, buffer.\n"
618 "\n"
619 "encoding gives the name of the encoding that the stream will be\n"
620 "decoded or encoded with. It defaults to locale.getpreferredencoding.\n"
621 "\n"
622 "errors determines the strictness of encoding and decoding (see the\n"
623 "codecs.register) and defaults to \"strict\".\n"
624 "\n"
625 "newline can be None, '', '\\n', '\\r', or '\\r\\n'. It controls the\n"
626 "handling of line endings. If it is None, universal newlines is\n"
627 "enabled. With this enabled, on input, the lines endings '\\n', '\\r',\n"
628 "or '\\r\\n' are translated to '\\n' before being returned to the\n"
629 "caller. Conversely, on output, '\\n' is translated to the system\n"
630 "default line seperator, os.linesep. If newline is any other of its\n"
631 "legal values, that newline becomes the newline when the file is read\n"
632 "and it is returned untranslated. On output, '\\n' is converted to the\n"
633 "newline.\n"
634 "\n"
635 "If line_buffering is True, a call to flush is implied when a call to\n"
636 "write contains a newline character."
637 );
638
639typedef PyObject *
640 (*encodefunc_t)(PyObject *, PyObject *);
641
642typedef struct
643{
644 PyObject_HEAD
645 int ok; /* initialized? */
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000646 int detached;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000647 Py_ssize_t chunk_size;
648 PyObject *buffer;
649 PyObject *encoding;
650 PyObject *encoder;
651 PyObject *decoder;
652 PyObject *readnl;
653 PyObject *errors;
654 const char *writenl; /* utf-8 encoded, NULL stands for \n */
655 char line_buffering;
Antoine Pitroue96ec682011-07-23 21:46:35 +0200656 char write_through;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000657 char readuniversal;
658 char readtranslate;
659 char writetranslate;
660 char seekable;
Antoine Pitroue96ec682011-07-23 21:46:35 +0200661 char has_read1;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000662 char telling;
Antoine Pitroue033e062010-10-29 10:38:18 +0000663 char deallocating;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000664 /* Specialized encoding func (see below) */
665 encodefunc_t encodefunc;
Antoine Pitroue4501852009-05-14 18:55:55 +0000666 /* Whether or not it's the start of the stream */
667 char encoding_start_of_stream;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000668
669 /* Reads and writes are internally buffered in order to speed things up.
670 However, any read will first flush the write buffer if itsn't empty.
Antoine Pitrou24f36292009-03-28 22:16:42 +0000671
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000672 Please also note that text to be written is first encoded before being
673 buffered. This is necessary so that encoding errors are immediately
674 reported to the caller, but it unfortunately means that the
675 IncrementalEncoder (whose encode() method is always written in Python)
676 becomes a bottleneck for small writes.
677 */
678 PyObject *decoded_chars; /* buffer for text returned from decoder */
679 Py_ssize_t decoded_chars_used; /* offset into _decoded_chars for read() */
680 PyObject *pending_bytes; /* list of bytes objects waiting to be
681 written, or NULL */
682 Py_ssize_t pending_bytes_count;
683 PyObject *snapshot;
684 /* snapshot is either None, or a tuple (dec_flags, next_input) where
685 * dec_flags is the second (integer) item of the decoder state and
686 * next_input is the chunk of input bytes that comes next after the
687 * snapshot point. We use this to reconstruct decoder states in tell().
688 */
689
690 /* Cache raw object if it's a FileIO object */
691 PyObject *raw;
692
693 PyObject *weakreflist;
694 PyObject *dict;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000695} textio;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000696
697
698/* A couple of specialized cases in order to bypass the slow incremental
699 encoding methods for the most popular encodings. */
700
701static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000702ascii_encode(textio *self, PyObject *text)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000703{
704 return PyUnicode_EncodeASCII(PyUnicode_AS_UNICODE(text),
705 PyUnicode_GET_SIZE(text),
706 PyBytes_AS_STRING(self->errors));
707}
708
709static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000710utf16be_encode(textio *self, PyObject *text)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000711{
712 return PyUnicode_EncodeUTF16(PyUnicode_AS_UNICODE(text),
713 PyUnicode_GET_SIZE(text),
714 PyBytes_AS_STRING(self->errors), 1);
715}
716
717static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000718utf16le_encode(textio *self, PyObject *text)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000719{
720 return PyUnicode_EncodeUTF16(PyUnicode_AS_UNICODE(text),
721 PyUnicode_GET_SIZE(text),
722 PyBytes_AS_STRING(self->errors), -1);
723}
724
725static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000726utf16_encode(textio *self, PyObject *text)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000727{
Antoine Pitroue4501852009-05-14 18:55:55 +0000728 if (!self->encoding_start_of_stream) {
729 /* Skip the BOM and use native byte ordering */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000730#if defined(WORDS_BIGENDIAN)
Antoine Pitroue4501852009-05-14 18:55:55 +0000731 return utf16be_encode(self, text);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000732#else
Antoine Pitroue4501852009-05-14 18:55:55 +0000733 return utf16le_encode(self, text);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000734#endif
Antoine Pitroue4501852009-05-14 18:55:55 +0000735 }
736 return PyUnicode_EncodeUTF16(PyUnicode_AS_UNICODE(text),
737 PyUnicode_GET_SIZE(text),
738 PyBytes_AS_STRING(self->errors), 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000739}
740
Antoine Pitroue4501852009-05-14 18:55:55 +0000741static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000742utf32be_encode(textio *self, PyObject *text)
Antoine Pitroue4501852009-05-14 18:55:55 +0000743{
744 return PyUnicode_EncodeUTF32(PyUnicode_AS_UNICODE(text),
745 PyUnicode_GET_SIZE(text),
746 PyBytes_AS_STRING(self->errors), 1);
747}
748
749static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000750utf32le_encode(textio *self, PyObject *text)
Antoine Pitroue4501852009-05-14 18:55:55 +0000751{
752 return PyUnicode_EncodeUTF32(PyUnicode_AS_UNICODE(text),
753 PyUnicode_GET_SIZE(text),
754 PyBytes_AS_STRING(self->errors), -1);
755}
756
757static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000758utf32_encode(textio *self, PyObject *text)
Antoine Pitroue4501852009-05-14 18:55:55 +0000759{
760 if (!self->encoding_start_of_stream) {
761 /* Skip the BOM and use native byte ordering */
762#if defined(WORDS_BIGENDIAN)
763 return utf32be_encode(self, text);
764#else
765 return utf32le_encode(self, text);
766#endif
767 }
768 return PyUnicode_EncodeUTF32(PyUnicode_AS_UNICODE(text),
769 PyUnicode_GET_SIZE(text),
770 PyBytes_AS_STRING(self->errors), 0);
771}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000772
773static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000774utf8_encode(textio *self, PyObject *text)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000775{
776 return PyUnicode_EncodeUTF8(PyUnicode_AS_UNICODE(text),
777 PyUnicode_GET_SIZE(text),
778 PyBytes_AS_STRING(self->errors));
779}
780
781static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000782latin1_encode(textio *self, PyObject *text)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000783{
784 return PyUnicode_EncodeLatin1(PyUnicode_AS_UNICODE(text),
785 PyUnicode_GET_SIZE(text),
786 PyBytes_AS_STRING(self->errors));
787}
788
789/* Map normalized encoding names onto the specialized encoding funcs */
790
791typedef struct {
792 const char *name;
793 encodefunc_t encodefunc;
794} encodefuncentry;
795
Antoine Pitrou24f36292009-03-28 22:16:42 +0000796static encodefuncentry encodefuncs[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000797 {"ascii", (encodefunc_t) ascii_encode},
798 {"iso8859-1", (encodefunc_t) latin1_encode},
Antoine Pitroue4501852009-05-14 18:55:55 +0000799 {"utf-8", (encodefunc_t) utf8_encode},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000800 {"utf-16-be", (encodefunc_t) utf16be_encode},
801 {"utf-16-le", (encodefunc_t) utf16le_encode},
802 {"utf-16", (encodefunc_t) utf16_encode},
Antoine Pitroue4501852009-05-14 18:55:55 +0000803 {"utf-32-be", (encodefunc_t) utf32be_encode},
804 {"utf-32-le", (encodefunc_t) utf32le_encode},
805 {"utf-32", (encodefunc_t) utf32_encode},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000806 {NULL, NULL}
807};
808
809
810static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000811textiowrapper_init(textio *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000812{
813 char *kwlist[] = {"buffer", "encoding", "errors",
Antoine Pitroue96ec682011-07-23 21:46:35 +0200814 "newline", "line_buffering", "write_through",
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000815 NULL};
816 PyObject *buffer, *raw;
817 char *encoding = NULL;
818 char *errors = NULL;
819 char *newline = NULL;
Antoine Pitroue96ec682011-07-23 21:46:35 +0200820 int line_buffering = 0, write_through = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000821 _PyIO_State *state = IO_STATE;
822
823 PyObject *res;
824 int r;
825
826 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000827 self->detached = 0;
Antoine Pitroue96ec682011-07-23 21:46:35 +0200828 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|zzzii:fileio",
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000829 kwlist, &buffer, &encoding, &errors,
Antoine Pitroue96ec682011-07-23 21:46:35 +0200830 &newline, &line_buffering, &write_through))
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000831 return -1;
832
833 if (newline && newline[0] != '\0'
834 && !(newline[0] == '\n' && newline[1] == '\0')
835 && !(newline[0] == '\r' && newline[1] == '\0')
836 && !(newline[0] == '\r' && newline[1] == '\n' && newline[2] == '\0')) {
837 PyErr_Format(PyExc_ValueError,
838 "illegal newline value: %s", newline);
839 return -1;
840 }
841
842 Py_CLEAR(self->buffer);
843 Py_CLEAR(self->encoding);
844 Py_CLEAR(self->encoder);
845 Py_CLEAR(self->decoder);
846 Py_CLEAR(self->readnl);
847 Py_CLEAR(self->decoded_chars);
848 Py_CLEAR(self->pending_bytes);
849 Py_CLEAR(self->snapshot);
850 Py_CLEAR(self->errors);
851 Py_CLEAR(self->raw);
852 self->decoded_chars_used = 0;
853 self->pending_bytes_count = 0;
854 self->encodefunc = NULL;
855
856 if (encoding == NULL) {
857 /* Try os.device_encoding(fileno) */
858 PyObject *fileno;
859 fileno = PyObject_CallMethod(buffer, "fileno", NULL);
860 /* Ignore only AttributeError and UnsupportedOperation */
861 if (fileno == NULL) {
862 if (PyErr_ExceptionMatches(PyExc_AttributeError) ||
863 PyErr_ExceptionMatches(state->unsupported_operation)) {
864 PyErr_Clear();
865 }
866 else {
867 goto error;
868 }
869 }
870 else {
871 self->encoding = PyObject_CallMethod(state->os_module,
872 "device_encoding",
873 "N", fileno);
874 if (self->encoding == NULL)
875 goto error;
876 else if (!PyUnicode_Check(self->encoding))
877 Py_CLEAR(self->encoding);
878 }
879 }
880 if (encoding == NULL && self->encoding == NULL) {
881 if (state->locale_module == NULL) {
882 state->locale_module = PyImport_ImportModule("locale");
883 if (state->locale_module == NULL)
884 goto catch_ImportError;
885 else
886 goto use_locale;
887 }
888 else {
889 use_locale:
890 self->encoding = PyObject_CallMethod(
891 state->locale_module, "getpreferredencoding", NULL);
892 if (self->encoding == NULL) {
893 catch_ImportError:
894 /*
895 Importing locale can raise a ImportError because of
896 _functools, and locale.getpreferredencoding can raise a
897 ImportError if _locale is not available. These will happen
898 during module building.
899 */
900 if (PyErr_ExceptionMatches(PyExc_ImportError)) {
901 PyErr_Clear();
902 self->encoding = PyUnicode_FromString("ascii");
903 }
904 else
905 goto error;
906 }
907 else if (!PyUnicode_Check(self->encoding))
908 Py_CLEAR(self->encoding);
909 }
910 }
Victor Stinnerf6c57832010-05-19 01:17:01 +0000911 if (self->encoding != NULL) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000912 encoding = _PyUnicode_AsString(self->encoding);
Victor Stinnerf6c57832010-05-19 01:17:01 +0000913 if (encoding == NULL)
914 goto error;
915 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000916 else if (encoding != NULL) {
917 self->encoding = PyUnicode_FromString(encoding);
918 if (self->encoding == NULL)
919 goto error;
920 }
921 else {
922 PyErr_SetString(PyExc_IOError,
923 "could not determine default encoding");
924 }
925
926 if (errors == NULL)
927 errors = "strict";
928 self->errors = PyBytes_FromString(errors);
929 if (self->errors == NULL)
930 goto error;
931
932 self->chunk_size = 8192;
933 self->readuniversal = (newline == NULL || newline[0] == '\0');
934 self->line_buffering = line_buffering;
Antoine Pitroue96ec682011-07-23 21:46:35 +0200935 self->write_through = write_through;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000936 self->readtranslate = (newline == NULL);
937 if (newline) {
938 self->readnl = PyUnicode_FromString(newline);
939 if (self->readnl == NULL)
940 return -1;
941 }
942 self->writetranslate = (newline == NULL || newline[0] != '\0');
943 if (!self->readuniversal && self->readnl) {
944 self->writenl = _PyUnicode_AsString(self->readnl);
Victor Stinnerf6c57832010-05-19 01:17:01 +0000945 if (self->writenl == NULL)
946 goto error;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000947 if (!strcmp(self->writenl, "\n"))
948 self->writenl = NULL;
949 }
950#ifdef MS_WINDOWS
951 else
952 self->writenl = "\r\n";
953#endif
954
955 /* Build the decoder object */
956 res = PyObject_CallMethod(buffer, "readable", NULL);
957 if (res == NULL)
958 goto error;
959 r = PyObject_IsTrue(res);
960 Py_DECREF(res);
961 if (r == -1)
962 goto error;
963 if (r == 1) {
964 self->decoder = PyCodec_IncrementalDecoder(
965 encoding, errors);
966 if (self->decoder == NULL)
967 goto error;
968
969 if (self->readuniversal) {
970 PyObject *incrementalDecoder = PyObject_CallFunction(
971 (PyObject *)&PyIncrementalNewlineDecoder_Type,
972 "Oi", self->decoder, (int)self->readtranslate);
973 if (incrementalDecoder == NULL)
974 goto error;
975 Py_CLEAR(self->decoder);
976 self->decoder = incrementalDecoder;
977 }
978 }
979
980 /* Build the encoder object */
981 res = PyObject_CallMethod(buffer, "writable", NULL);
982 if (res == NULL)
983 goto error;
984 r = PyObject_IsTrue(res);
985 Py_DECREF(res);
986 if (r == -1)
987 goto error;
988 if (r == 1) {
989 PyObject *ci;
990 self->encoder = PyCodec_IncrementalEncoder(
991 encoding, errors);
992 if (self->encoder == NULL)
993 goto error;
994 /* Get the normalized named of the codec */
995 ci = _PyCodec_Lookup(encoding);
996 if (ci == NULL)
997 goto error;
998 res = PyObject_GetAttrString(ci, "name");
999 Py_DECREF(ci);
Benjamin Peterson2cfca792009-06-06 20:46:48 +00001000 if (res == NULL) {
1001 if (PyErr_ExceptionMatches(PyExc_AttributeError))
1002 PyErr_Clear();
1003 else
1004 goto error;
1005 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001006 else if (PyUnicode_Check(res)) {
1007 encodefuncentry *e = encodefuncs;
1008 while (e->name != NULL) {
1009 if (!PyUnicode_CompareWithASCIIString(res, e->name)) {
1010 self->encodefunc = e->encodefunc;
1011 break;
1012 }
1013 e++;
1014 }
1015 }
1016 Py_XDECREF(res);
1017 }
1018
1019 self->buffer = buffer;
1020 Py_INCREF(buffer);
Antoine Pitrou24f36292009-03-28 22:16:42 +00001021
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001022 if (Py_TYPE(buffer) == &PyBufferedReader_Type ||
1023 Py_TYPE(buffer) == &PyBufferedWriter_Type ||
1024 Py_TYPE(buffer) == &PyBufferedRandom_Type) {
1025 raw = PyObject_GetAttrString(buffer, "raw");
1026 /* Cache the raw FileIO object to speed up 'closed' checks */
Benjamin Peterson2cfca792009-06-06 20:46:48 +00001027 if (raw == NULL) {
1028 if (PyErr_ExceptionMatches(PyExc_AttributeError))
1029 PyErr_Clear();
1030 else
1031 goto error;
1032 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001033 else if (Py_TYPE(raw) == &PyFileIO_Type)
1034 self->raw = raw;
1035 else
1036 Py_DECREF(raw);
1037 }
1038
1039 res = PyObject_CallMethod(buffer, "seekable", NULL);
1040 if (res == NULL)
1041 goto error;
1042 self->seekable = self->telling = PyObject_IsTrue(res);
1043 Py_DECREF(res);
1044
Antoine Pitroue96ec682011-07-23 21:46:35 +02001045 self->has_read1 = PyObject_HasAttrString(buffer, "read1");
1046
Antoine Pitroue4501852009-05-14 18:55:55 +00001047 self->encoding_start_of_stream = 0;
1048 if (self->seekable && self->encoder) {
1049 PyObject *cookieObj;
1050 int cmp;
1051
1052 self->encoding_start_of_stream = 1;
1053
1054 cookieObj = PyObject_CallMethodObjArgs(buffer, _PyIO_str_tell, NULL);
1055 if (cookieObj == NULL)
1056 goto error;
1057
1058 cmp = PyObject_RichCompareBool(cookieObj, _PyIO_zero, Py_EQ);
1059 Py_DECREF(cookieObj);
1060 if (cmp < 0) {
1061 goto error;
1062 }
1063
1064 if (cmp == 0) {
1065 self->encoding_start_of_stream = 0;
1066 res = PyObject_CallMethodObjArgs(self->encoder, _PyIO_str_setstate,
1067 _PyIO_zero, NULL);
1068 if (res == NULL)
1069 goto error;
1070 Py_DECREF(res);
1071 }
1072 }
1073
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001074 self->ok = 1;
1075 return 0;
1076
1077 error:
1078 return -1;
1079}
1080
1081static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001082_textiowrapper_clear(textio *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001083{
1084 if (self->ok && _PyIOBase_finalize((PyObject *) self) < 0)
1085 return -1;
1086 self->ok = 0;
1087 Py_CLEAR(self->buffer);
1088 Py_CLEAR(self->encoding);
1089 Py_CLEAR(self->encoder);
1090 Py_CLEAR(self->decoder);
1091 Py_CLEAR(self->readnl);
1092 Py_CLEAR(self->decoded_chars);
1093 Py_CLEAR(self->pending_bytes);
1094 Py_CLEAR(self->snapshot);
1095 Py_CLEAR(self->errors);
1096 Py_CLEAR(self->raw);
1097 return 0;
1098}
1099
1100static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001101textiowrapper_dealloc(textio *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001102{
Antoine Pitroue033e062010-10-29 10:38:18 +00001103 self->deallocating = 1;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001104 if (_textiowrapper_clear(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001105 return;
1106 _PyObject_GC_UNTRACK(self);
1107 if (self->weakreflist != NULL)
1108 PyObject_ClearWeakRefs((PyObject *)self);
1109 Py_CLEAR(self->dict);
1110 Py_TYPE(self)->tp_free((PyObject *)self);
1111}
1112
1113static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001114textiowrapper_traverse(textio *self, visitproc visit, void *arg)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001115{
1116 Py_VISIT(self->buffer);
1117 Py_VISIT(self->encoding);
1118 Py_VISIT(self->encoder);
1119 Py_VISIT(self->decoder);
1120 Py_VISIT(self->readnl);
1121 Py_VISIT(self->decoded_chars);
1122 Py_VISIT(self->pending_bytes);
1123 Py_VISIT(self->snapshot);
1124 Py_VISIT(self->errors);
1125 Py_VISIT(self->raw);
1126
1127 Py_VISIT(self->dict);
1128 return 0;
1129}
1130
1131static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001132textiowrapper_clear(textio *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001133{
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001134 if (_textiowrapper_clear(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001135 return -1;
1136 Py_CLEAR(self->dict);
1137 return 0;
1138}
1139
1140static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001141textiowrapper_closed_get(textio *self, void *context);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001142
1143/* This macro takes some shortcuts to make the common case faster. */
1144#define CHECK_CLOSED(self) \
1145 do { \
1146 int r; \
1147 PyObject *_res; \
1148 if (Py_TYPE(self) == &PyTextIOWrapper_Type) { \
1149 if (self->raw != NULL) \
1150 r = _PyFileIO_closed(self->raw); \
1151 else { \
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001152 _res = textiowrapper_closed_get(self, NULL); \
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001153 if (_res == NULL) \
1154 return NULL; \
1155 r = PyObject_IsTrue(_res); \
1156 Py_DECREF(_res); \
1157 if (r < 0) \
1158 return NULL; \
1159 } \
1160 if (r > 0) { \
1161 PyErr_SetString(PyExc_ValueError, \
1162 "I/O operation on closed file."); \
1163 return NULL; \
1164 } \
1165 } \
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001166 else if (_PyIOBase_check_closed((PyObject *)self, Py_True) == NULL) \
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001167 return NULL; \
1168 } while (0)
1169
1170#define CHECK_INITIALIZED(self) \
1171 if (self->ok <= 0) { \
Benjamin Petersond2e0c792009-05-01 20:40:59 +00001172 if (self->detached) { \
1173 PyErr_SetString(PyExc_ValueError, \
1174 "underlying buffer has been detached"); \
1175 } else { \
1176 PyErr_SetString(PyExc_ValueError, \
1177 "I/O operation on uninitialized object"); \
1178 } \
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001179 return NULL; \
1180 }
1181
1182#define CHECK_INITIALIZED_INT(self) \
1183 if (self->ok <= 0) { \
Benjamin Petersond2e0c792009-05-01 20:40:59 +00001184 if (self->detached) { \
1185 PyErr_SetString(PyExc_ValueError, \
1186 "underlying buffer has been detached"); \
1187 } else { \
1188 PyErr_SetString(PyExc_ValueError, \
1189 "I/O operation on uninitialized object"); \
1190 } \
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001191 return -1; \
1192 }
1193
1194
Benjamin Petersond2e0c792009-05-01 20:40:59 +00001195static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001196textiowrapper_detach(textio *self)
Benjamin Petersond2e0c792009-05-01 20:40:59 +00001197{
1198 PyObject *buffer, *res;
1199 CHECK_INITIALIZED(self);
1200 res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);
1201 if (res == NULL)
1202 return NULL;
1203 Py_DECREF(res);
1204 buffer = self->buffer;
1205 self->buffer = NULL;
1206 self->detached = 1;
1207 self->ok = 0;
1208 return buffer;
1209}
1210
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001211Py_LOCAL_INLINE(const Py_UNICODE *)
1212findchar(const Py_UNICODE *s, Py_ssize_t size, Py_UNICODE ch)
1213{
1214 /* like wcschr, but doesn't stop at NULL characters */
1215 while (size-- > 0) {
1216 if (*s == ch)
1217 return s;
1218 s++;
1219 }
1220 return NULL;
1221}
1222
Antoine Pitrou24f36292009-03-28 22:16:42 +00001223/* Flush the internal write buffer. This doesn't explicitly flush the
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001224 underlying buffered object, though. */
1225static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001226_textiowrapper_writeflush(textio *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001227{
Amaury Forgeot d'Arcccd686a2009-08-29 23:00:38 +00001228 PyObject *pending, *b, *ret;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001229
1230 if (self->pending_bytes == NULL)
1231 return 0;
Amaury Forgeot d'Arcccd686a2009-08-29 23:00:38 +00001232
1233 pending = self->pending_bytes;
1234 Py_INCREF(pending);
1235 self->pending_bytes_count = 0;
1236 Py_CLEAR(self->pending_bytes);
1237
1238 b = _PyBytes_Join(_PyIO_empty_bytes, pending);
1239 Py_DECREF(pending);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001240 if (b == NULL)
1241 return -1;
1242 ret = PyObject_CallMethodObjArgs(self->buffer,
1243 _PyIO_str_write, b, NULL);
1244 Py_DECREF(b);
1245 if (ret == NULL)
1246 return -1;
1247 Py_DECREF(ret);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001248 return 0;
1249}
1250
1251static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001252textiowrapper_write(textio *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001253{
1254 PyObject *ret;
1255 PyObject *text; /* owned reference */
1256 PyObject *b;
1257 Py_ssize_t textlen;
1258 int haslf = 0;
1259 int needflush = 0;
1260
1261 CHECK_INITIALIZED(self);
1262
1263 if (!PyArg_ParseTuple(args, "U:write", &text)) {
1264 return NULL;
1265 }
1266
1267 CHECK_CLOSED(self);
1268
Antoine Pitrou0d739d72010-09-05 23:01:12 +00001269 if (self->encoder == NULL)
1270 return _unsupported("not writable");
Benjamin Peterson81971ea2009-05-14 22:01:31 +00001271
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001272 Py_INCREF(text);
1273
1274 textlen = PyUnicode_GetSize(text);
1275
1276 if ((self->writetranslate && self->writenl != NULL) || self->line_buffering)
1277 if (findchar(PyUnicode_AS_UNICODE(text),
1278 PyUnicode_GET_SIZE(text), '\n'))
1279 haslf = 1;
1280
1281 if (haslf && self->writetranslate && self->writenl != NULL) {
1282 PyObject *newtext = PyObject_CallMethod(
1283 text, "replace", "ss", "\n", self->writenl);
1284 Py_DECREF(text);
1285 if (newtext == NULL)
1286 return NULL;
1287 text = newtext;
1288 }
1289
Antoine Pitroue96ec682011-07-23 21:46:35 +02001290 if (self->write_through)
1291 needflush = 1;
1292 else if (self->line_buffering &&
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001293 (haslf ||
1294 findchar(PyUnicode_AS_UNICODE(text),
1295 PyUnicode_GET_SIZE(text), '\r')))
1296 needflush = 1;
1297
1298 /* XXX What if we were just reading? */
Antoine Pitroue4501852009-05-14 18:55:55 +00001299 if (self->encodefunc != NULL) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001300 b = (*self->encodefunc)((PyObject *) self, text);
Antoine Pitroue4501852009-05-14 18:55:55 +00001301 self->encoding_start_of_stream = 0;
1302 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001303 else
1304 b = PyObject_CallMethodObjArgs(self->encoder,
1305 _PyIO_str_encode, text, NULL);
1306 Py_DECREF(text);
1307 if (b == NULL)
1308 return NULL;
1309
1310 if (self->pending_bytes == NULL) {
1311 self->pending_bytes = PyList_New(0);
1312 if (self->pending_bytes == NULL) {
1313 Py_DECREF(b);
1314 return NULL;
1315 }
1316 self->pending_bytes_count = 0;
1317 }
1318 if (PyList_Append(self->pending_bytes, b) < 0) {
1319 Py_DECREF(b);
1320 return NULL;
1321 }
1322 self->pending_bytes_count += PyBytes_GET_SIZE(b);
1323 Py_DECREF(b);
1324 if (self->pending_bytes_count > self->chunk_size || needflush) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001325 if (_textiowrapper_writeflush(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001326 return NULL;
1327 }
Antoine Pitrou24f36292009-03-28 22:16:42 +00001328
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001329 if (needflush) {
1330 ret = PyObject_CallMethodObjArgs(self->buffer, _PyIO_str_flush, NULL);
1331 if (ret == NULL)
1332 return NULL;
1333 Py_DECREF(ret);
1334 }
1335
1336 Py_CLEAR(self->snapshot);
1337
1338 if (self->decoder) {
1339 ret = PyObject_CallMethod(self->decoder, "reset", NULL);
1340 if (ret == NULL)
1341 return NULL;
1342 Py_DECREF(ret);
1343 }
1344
1345 return PyLong_FromSsize_t(textlen);
1346}
1347
1348/* Steal a reference to chars and store it in the decoded_char buffer;
1349 */
1350static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001351textiowrapper_set_decoded_chars(textio *self, PyObject *chars)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001352{
1353 Py_CLEAR(self->decoded_chars);
1354 self->decoded_chars = chars;
1355 self->decoded_chars_used = 0;
1356}
1357
1358static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001359textiowrapper_get_decoded_chars(textio *self, Py_ssize_t n)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001360{
1361 PyObject *chars;
1362 Py_ssize_t avail;
1363
1364 if (self->decoded_chars == NULL)
1365 return PyUnicode_FromStringAndSize(NULL, 0);
1366
1367 avail = (PyUnicode_GET_SIZE(self->decoded_chars)
1368 - self->decoded_chars_used);
1369
1370 assert(avail >= 0);
1371
1372 if (n < 0 || n > avail)
1373 n = avail;
1374
1375 if (self->decoded_chars_used > 0 || n < avail) {
1376 chars = PyUnicode_FromUnicode(
1377 PyUnicode_AS_UNICODE(self->decoded_chars)
1378 + self->decoded_chars_used, n);
1379 if (chars == NULL)
1380 return NULL;
1381 }
1382 else {
1383 chars = self->decoded_chars;
1384 Py_INCREF(chars);
1385 }
1386
1387 self->decoded_chars_used += n;
1388 return chars;
1389}
1390
1391/* Read and decode the next chunk of data from the BufferedReader.
1392 */
1393static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001394textiowrapper_read_chunk(textio *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001395{
1396 PyObject *dec_buffer = NULL;
1397 PyObject *dec_flags = NULL;
1398 PyObject *input_chunk = NULL;
1399 PyObject *decoded_chars, *chunk_size;
1400 int eof;
1401
1402 /* The return value is True unless EOF was reached. The decoded string is
1403 * placed in self._decoded_chars (replacing its previous value). The
1404 * entire input chunk is sent to the decoder, though some of it may remain
1405 * buffered in the decoder, yet to be converted.
1406 */
1407
1408 if (self->decoder == NULL) {
Antoine Pitrou0d739d72010-09-05 23:01:12 +00001409 _unsupported("not readable");
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001410 return -1;
1411 }
1412
1413 if (self->telling) {
1414 /* To prepare for tell(), we need to snapshot a point in the file
1415 * where the decoder's input buffer is empty.
1416 */
1417
1418 PyObject *state = PyObject_CallMethodObjArgs(self->decoder,
1419 _PyIO_str_getstate, NULL);
1420 if (state == NULL)
1421 return -1;
1422 /* Given this, we know there was a valid snapshot point
1423 * len(dec_buffer) bytes ago with decoder state (b'', dec_flags).
1424 */
1425 if (PyArg_Parse(state, "(OO)", &dec_buffer, &dec_flags) < 0) {
1426 Py_DECREF(state);
1427 return -1;
1428 }
1429 Py_INCREF(dec_buffer);
1430 Py_INCREF(dec_flags);
1431 Py_DECREF(state);
1432 }
1433
1434 /* Read a chunk, decode it, and put the result in self._decoded_chars. */
1435 chunk_size = PyLong_FromSsize_t(self->chunk_size);
1436 if (chunk_size == NULL)
1437 goto fail;
1438 input_chunk = PyObject_CallMethodObjArgs(self->buffer,
Antoine Pitroue96ec682011-07-23 21:46:35 +02001439 (self->has_read1 ? _PyIO_str_read1: _PyIO_str_read),
1440 chunk_size, NULL);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001441 Py_DECREF(chunk_size);
1442 if (input_chunk == NULL)
1443 goto fail;
1444 assert(PyBytes_Check(input_chunk));
1445
1446 eof = (PyBytes_Size(input_chunk) == 0);
1447
1448 if (Py_TYPE(self->decoder) == &PyIncrementalNewlineDecoder_Type) {
1449 decoded_chars = _PyIncrementalNewlineDecoder_decode(
1450 self->decoder, input_chunk, eof);
1451 }
1452 else {
1453 decoded_chars = PyObject_CallMethodObjArgs(self->decoder,
1454 _PyIO_str_decode, input_chunk, eof ? Py_True : Py_False, NULL);
1455 }
1456
1457 /* TODO sanity check: isinstance(decoded_chars, unicode) */
1458 if (decoded_chars == NULL)
1459 goto fail;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001460 textiowrapper_set_decoded_chars(self, decoded_chars);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001461 if (PyUnicode_GET_SIZE(decoded_chars) > 0)
1462 eof = 0;
1463
1464 if (self->telling) {
1465 /* At the snapshot point, len(dec_buffer) bytes before the read, the
1466 * next input to be decoded is dec_buffer + input_chunk.
1467 */
1468 PyObject *next_input = PyNumber_Add(dec_buffer, input_chunk);
1469 if (next_input == NULL)
1470 goto fail;
1471 assert (PyBytes_Check(next_input));
1472 Py_DECREF(dec_buffer);
1473 Py_CLEAR(self->snapshot);
1474 self->snapshot = Py_BuildValue("NN", dec_flags, next_input);
1475 }
1476 Py_DECREF(input_chunk);
1477
1478 return (eof == 0);
1479
1480 fail:
1481 Py_XDECREF(dec_buffer);
1482 Py_XDECREF(dec_flags);
1483 Py_XDECREF(input_chunk);
1484 return -1;
1485}
1486
1487static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001488textiowrapper_read(textio *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001489{
1490 Py_ssize_t n = -1;
1491 PyObject *result = NULL, *chunks = NULL;
1492
1493 CHECK_INITIALIZED(self);
1494
Benjamin Petersonbf5ff762009-12-13 19:25:34 +00001495 if (!PyArg_ParseTuple(args, "|O&:read", &_PyIO_ConvertSsize_t, &n))
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001496 return NULL;
1497
1498 CHECK_CLOSED(self);
1499
Antoine Pitrou0d739d72010-09-05 23:01:12 +00001500 if (self->decoder == NULL)
1501 return _unsupported("not readable");
Benjamin Petersona1b49012009-03-31 23:11:32 +00001502
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001503 if (_textiowrapper_writeflush(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001504 return NULL;
1505
1506 if (n < 0) {
1507 /* Read everything */
1508 PyObject *bytes = PyObject_CallMethod(self->buffer, "read", NULL);
1509 PyObject *decoded;
1510 if (bytes == NULL)
1511 goto fail;
1512 decoded = PyObject_CallMethodObjArgs(self->decoder, _PyIO_str_decode,
1513 bytes, Py_True, NULL);
1514 Py_DECREF(bytes);
1515 if (decoded == NULL)
1516 goto fail;
1517
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001518 result = textiowrapper_get_decoded_chars(self, -1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001519
1520 if (result == NULL) {
1521 Py_DECREF(decoded);
1522 return NULL;
1523 }
1524
1525 PyUnicode_AppendAndDel(&result, decoded);
1526 if (result == NULL)
1527 goto fail;
1528
1529 Py_CLEAR(self->snapshot);
1530 return result;
1531 }
1532 else {
1533 int res = 1;
1534 Py_ssize_t remaining = n;
1535
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001536 result = textiowrapper_get_decoded_chars(self, n);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001537 if (result == NULL)
1538 goto fail;
1539 remaining -= PyUnicode_GET_SIZE(result);
1540
1541 /* Keep reading chunks until we have n characters to return */
1542 while (remaining > 0) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001543 res = textiowrapper_read_chunk(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001544 if (res < 0)
1545 goto fail;
1546 if (res == 0) /* EOF */
1547 break;
1548 if (chunks == NULL) {
1549 chunks = PyList_New(0);
1550 if (chunks == NULL)
1551 goto fail;
1552 }
1553 if (PyList_Append(chunks, result) < 0)
1554 goto fail;
1555 Py_DECREF(result);
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001556 result = textiowrapper_get_decoded_chars(self, remaining);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001557 if (result == NULL)
1558 goto fail;
1559 remaining -= PyUnicode_GET_SIZE(result);
1560 }
1561 if (chunks != NULL) {
1562 if (result != NULL && PyList_Append(chunks, result) < 0)
1563 goto fail;
1564 Py_CLEAR(result);
1565 result = PyUnicode_Join(_PyIO_empty_str, chunks);
1566 if (result == NULL)
1567 goto fail;
1568 Py_CLEAR(chunks);
1569 }
1570 return result;
1571 }
1572 fail:
1573 Py_XDECREF(result);
1574 Py_XDECREF(chunks);
1575 return NULL;
1576}
1577
1578
1579/* NOTE: `end` must point to the real end of the Py_UNICODE storage,
1580 that is to the NUL character. Otherwise the function will produce
1581 incorrect results. */
1582static Py_UNICODE *
1583find_control_char(Py_UNICODE *start, Py_UNICODE *end, Py_UNICODE ch)
1584{
1585 Py_UNICODE *s = start;
1586 for (;;) {
1587 while (*s > ch)
1588 s++;
1589 if (*s == ch)
1590 return s;
1591 if (s == end)
1592 return NULL;
1593 s++;
1594 }
1595}
1596
1597Py_ssize_t
1598_PyIO_find_line_ending(
1599 int translated, int universal, PyObject *readnl,
1600 Py_UNICODE *start, Py_UNICODE *end, Py_ssize_t *consumed)
1601{
1602 Py_ssize_t len = end - start;
1603
1604 if (translated) {
1605 /* Newlines are already translated, only search for \n */
1606 Py_UNICODE *pos = find_control_char(start, end, '\n');
1607 if (pos != NULL)
1608 return pos - start + 1;
1609 else {
1610 *consumed = len;
1611 return -1;
1612 }
1613 }
1614 else if (universal) {
1615 /* Universal newline search. Find any of \r, \r\n, \n
1616 * The decoder ensures that \r\n are not split in two pieces
1617 */
1618 Py_UNICODE *s = start;
1619 for (;;) {
1620 Py_UNICODE ch;
1621 /* Fast path for non-control chars. The loop always ends
1622 since the Py_UNICODE storage is NUL-terminated. */
1623 while (*s > '\r')
1624 s++;
1625 if (s >= end) {
1626 *consumed = len;
1627 return -1;
1628 }
1629 ch = *s++;
1630 if (ch == '\n')
1631 return s - start;
1632 if (ch == '\r') {
1633 if (*s == '\n')
1634 return s - start + 1;
1635 else
1636 return s - start;
1637 }
1638 }
1639 }
1640 else {
1641 /* Non-universal mode. */
1642 Py_ssize_t readnl_len = PyUnicode_GET_SIZE(readnl);
1643 Py_UNICODE *nl = PyUnicode_AS_UNICODE(readnl);
1644 if (readnl_len == 1) {
1645 Py_UNICODE *pos = find_control_char(start, end, nl[0]);
1646 if (pos != NULL)
1647 return pos - start + 1;
1648 *consumed = len;
1649 return -1;
1650 }
1651 else {
1652 Py_UNICODE *s = start;
1653 Py_UNICODE *e = end - readnl_len + 1;
1654 Py_UNICODE *pos;
1655 if (e < s)
1656 e = s;
1657 while (s < e) {
1658 Py_ssize_t i;
1659 Py_UNICODE *pos = find_control_char(s, end, nl[0]);
1660 if (pos == NULL || pos >= e)
1661 break;
1662 for (i = 1; i < readnl_len; i++) {
1663 if (pos[i] != nl[i])
1664 break;
1665 }
1666 if (i == readnl_len)
1667 return pos - start + readnl_len;
1668 s = pos + 1;
1669 }
1670 pos = find_control_char(e, end, nl[0]);
1671 if (pos == NULL)
1672 *consumed = len;
1673 else
1674 *consumed = pos - start;
1675 return -1;
1676 }
1677 }
1678}
1679
1680static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001681_textiowrapper_readline(textio *self, Py_ssize_t limit)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001682{
1683 PyObject *line = NULL, *chunks = NULL, *remaining = NULL;
1684 Py_ssize_t start, endpos, chunked, offset_to_buffer;
1685 int res;
1686
1687 CHECK_CLOSED(self);
1688
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001689 if (_textiowrapper_writeflush(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001690 return NULL;
1691
1692 chunked = 0;
1693
1694 while (1) {
1695 Py_UNICODE *ptr;
1696 Py_ssize_t line_len;
1697 Py_ssize_t consumed = 0;
1698
1699 /* First, get some data if necessary */
1700 res = 1;
1701 while (!self->decoded_chars ||
1702 !PyUnicode_GET_SIZE(self->decoded_chars)) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001703 res = textiowrapper_read_chunk(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001704 if (res < 0)
1705 goto error;
1706 if (res == 0)
1707 break;
1708 }
1709 if (res == 0) {
1710 /* end of file */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001711 textiowrapper_set_decoded_chars(self, NULL);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001712 Py_CLEAR(self->snapshot);
1713 start = endpos = offset_to_buffer = 0;
1714 break;
1715 }
1716
1717 if (remaining == NULL) {
1718 line = self->decoded_chars;
1719 start = self->decoded_chars_used;
1720 offset_to_buffer = 0;
1721 Py_INCREF(line);
1722 }
1723 else {
1724 assert(self->decoded_chars_used == 0);
1725 line = PyUnicode_Concat(remaining, self->decoded_chars);
1726 start = 0;
1727 offset_to_buffer = PyUnicode_GET_SIZE(remaining);
1728 Py_CLEAR(remaining);
1729 if (line == NULL)
1730 goto error;
1731 }
1732
1733 ptr = PyUnicode_AS_UNICODE(line);
1734 line_len = PyUnicode_GET_SIZE(line);
1735
1736 endpos = _PyIO_find_line_ending(
1737 self->readtranslate, self->readuniversal, self->readnl,
1738 ptr + start, ptr + line_len, &consumed);
1739 if (endpos >= 0) {
1740 endpos += start;
1741 if (limit >= 0 && (endpos - start) + chunked >= limit)
1742 endpos = start + limit - chunked;
1743 break;
1744 }
1745
1746 /* We can put aside up to `endpos` */
1747 endpos = consumed + start;
1748 if (limit >= 0 && (endpos - start) + chunked >= limit) {
1749 /* Didn't find line ending, but reached length limit */
1750 endpos = start + limit - chunked;
1751 break;
1752 }
1753
1754 if (endpos > start) {
1755 /* No line ending seen yet - put aside current data */
1756 PyObject *s;
1757 if (chunks == NULL) {
1758 chunks = PyList_New(0);
1759 if (chunks == NULL)
1760 goto error;
1761 }
1762 s = PyUnicode_FromUnicode(ptr + start, endpos - start);
1763 if (s == NULL)
1764 goto error;
1765 if (PyList_Append(chunks, s) < 0) {
1766 Py_DECREF(s);
1767 goto error;
1768 }
1769 chunked += PyUnicode_GET_SIZE(s);
1770 Py_DECREF(s);
1771 }
1772 /* There may be some remaining bytes we'll have to prepend to the
1773 next chunk of data */
1774 if (endpos < line_len) {
1775 remaining = PyUnicode_FromUnicode(
1776 ptr + endpos, line_len - endpos);
1777 if (remaining == NULL)
1778 goto error;
1779 }
1780 Py_CLEAR(line);
1781 /* We have consumed the buffer */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001782 textiowrapper_set_decoded_chars(self, NULL);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001783 }
1784
1785 if (line != NULL) {
1786 /* Our line ends in the current buffer */
1787 self->decoded_chars_used = endpos - offset_to_buffer;
1788 if (start > 0 || endpos < PyUnicode_GET_SIZE(line)) {
1789 if (start == 0 && Py_REFCNT(line) == 1) {
1790 if (PyUnicode_Resize(&line, endpos) < 0)
1791 goto error;
1792 }
1793 else {
1794 PyObject *s = PyUnicode_FromUnicode(
1795 PyUnicode_AS_UNICODE(line) + start, endpos - start);
1796 Py_CLEAR(line);
1797 if (s == NULL)
1798 goto error;
1799 line = s;
1800 }
1801 }
1802 }
1803 if (remaining != NULL) {
1804 if (chunks == NULL) {
1805 chunks = PyList_New(0);
1806 if (chunks == NULL)
1807 goto error;
1808 }
1809 if (PyList_Append(chunks, remaining) < 0)
1810 goto error;
1811 Py_CLEAR(remaining);
1812 }
1813 if (chunks != NULL) {
1814 if (line != NULL && PyList_Append(chunks, line) < 0)
1815 goto error;
1816 Py_CLEAR(line);
1817 line = PyUnicode_Join(_PyIO_empty_str, chunks);
1818 if (line == NULL)
1819 goto error;
1820 Py_DECREF(chunks);
1821 }
1822 if (line == NULL)
1823 line = PyUnicode_FromStringAndSize(NULL, 0);
1824
1825 return line;
1826
1827 error:
1828 Py_XDECREF(chunks);
1829 Py_XDECREF(remaining);
1830 Py_XDECREF(line);
1831 return NULL;
1832}
1833
1834static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001835textiowrapper_readline(textio *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001836{
1837 Py_ssize_t limit = -1;
1838
1839 CHECK_INITIALIZED(self);
1840 if (!PyArg_ParseTuple(args, "|n:readline", &limit)) {
1841 return NULL;
1842 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001843 return _textiowrapper_readline(self, limit);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001844}
1845
1846/* Seek and Tell */
1847
1848typedef struct {
1849 Py_off_t start_pos;
1850 int dec_flags;
1851 int bytes_to_feed;
1852 int chars_to_skip;
1853 char need_eof;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001854} cookie_type;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001855
1856/*
1857 To speed up cookie packing/unpacking, we store the fields in a temporary
1858 string and call _PyLong_FromByteArray() or _PyLong_AsByteArray (resp.).
1859 The following macros define at which offsets in the intermediary byte
1860 string the various CookieStruct fields will be stored.
1861 */
1862
1863#define COOKIE_BUF_LEN (sizeof(Py_off_t) + 3 * sizeof(int) + sizeof(char))
1864
1865#if defined(WORDS_BIGENDIAN)
1866
1867# define IS_LITTLE_ENDIAN 0
1868
1869/* We want the least significant byte of start_pos to also be the least
1870 significant byte of the cookie, which means that in big-endian mode we
1871 must copy the fields in reverse order. */
1872
1873# define OFF_START_POS (sizeof(char) + 3 * sizeof(int))
1874# define OFF_DEC_FLAGS (sizeof(char) + 2 * sizeof(int))
1875# define OFF_BYTES_TO_FEED (sizeof(char) + sizeof(int))
1876# define OFF_CHARS_TO_SKIP (sizeof(char))
1877# define OFF_NEED_EOF 0
1878
1879#else
1880
1881# define IS_LITTLE_ENDIAN 1
1882
1883/* Little-endian mode: the least significant byte of start_pos will
1884 naturally end up the least significant byte of the cookie. */
1885
1886# define OFF_START_POS 0
1887# define OFF_DEC_FLAGS (sizeof(Py_off_t))
1888# define OFF_BYTES_TO_FEED (sizeof(Py_off_t) + sizeof(int))
1889# define OFF_CHARS_TO_SKIP (sizeof(Py_off_t) + 2 * sizeof(int))
1890# define OFF_NEED_EOF (sizeof(Py_off_t) + 3 * sizeof(int))
1891
1892#endif
1893
1894static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001895textiowrapper_parse_cookie(cookie_type *cookie, PyObject *cookieObj)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001896{
1897 unsigned char buffer[COOKIE_BUF_LEN];
1898 PyLongObject *cookieLong = (PyLongObject *)PyNumber_Long(cookieObj);
1899 if (cookieLong == NULL)
1900 return -1;
1901
1902 if (_PyLong_AsByteArray(cookieLong, buffer, sizeof(buffer),
1903 IS_LITTLE_ENDIAN, 0) < 0) {
1904 Py_DECREF(cookieLong);
1905 return -1;
1906 }
1907 Py_DECREF(cookieLong);
1908
Antoine Pitrou2db74c22009-03-06 21:49:02 +00001909 memcpy(&cookie->start_pos, buffer + OFF_START_POS, sizeof(cookie->start_pos));
1910 memcpy(&cookie->dec_flags, buffer + OFF_DEC_FLAGS, sizeof(cookie->dec_flags));
1911 memcpy(&cookie->bytes_to_feed, buffer + OFF_BYTES_TO_FEED, sizeof(cookie->bytes_to_feed));
1912 memcpy(&cookie->chars_to_skip, buffer + OFF_CHARS_TO_SKIP, sizeof(cookie->chars_to_skip));
1913 memcpy(&cookie->need_eof, buffer + OFF_NEED_EOF, sizeof(cookie->need_eof));
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001914
1915 return 0;
1916}
1917
1918static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001919textiowrapper_build_cookie(cookie_type *cookie)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001920{
1921 unsigned char buffer[COOKIE_BUF_LEN];
1922
Antoine Pitrou2db74c22009-03-06 21:49:02 +00001923 memcpy(buffer + OFF_START_POS, &cookie->start_pos, sizeof(cookie->start_pos));
1924 memcpy(buffer + OFF_DEC_FLAGS, &cookie->dec_flags, sizeof(cookie->dec_flags));
1925 memcpy(buffer + OFF_BYTES_TO_FEED, &cookie->bytes_to_feed, sizeof(cookie->bytes_to_feed));
1926 memcpy(buffer + OFF_CHARS_TO_SKIP, &cookie->chars_to_skip, sizeof(cookie->chars_to_skip));
1927 memcpy(buffer + OFF_NEED_EOF, &cookie->need_eof, sizeof(cookie->need_eof));
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001928
1929 return _PyLong_FromByteArray(buffer, sizeof(buffer), IS_LITTLE_ENDIAN, 0);
1930}
1931#undef IS_LITTLE_ENDIAN
1932
1933static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001934_textiowrapper_decoder_setstate(textio *self, cookie_type *cookie)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001935{
1936 PyObject *res;
1937 /* When seeking to the start of the stream, we call decoder.reset()
1938 rather than decoder.getstate().
1939 This is for a few decoders such as utf-16 for which the state value
1940 at start is not (b"", 0) but e.g. (b"", 2) (meaning, in the case of
1941 utf-16, that we are expecting a BOM).
1942 */
1943 if (cookie->start_pos == 0 && cookie->dec_flags == 0)
1944 res = PyObject_CallMethodObjArgs(self->decoder, _PyIO_str_reset, NULL);
1945 else
1946 res = PyObject_CallMethod(self->decoder, "setstate",
1947 "((yi))", "", cookie->dec_flags);
1948 if (res == NULL)
1949 return -1;
1950 Py_DECREF(res);
1951 return 0;
1952}
1953
Antoine Pitroue4501852009-05-14 18:55:55 +00001954static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001955_textiowrapper_encoder_setstate(textio *self, cookie_type *cookie)
Antoine Pitroue4501852009-05-14 18:55:55 +00001956{
1957 PyObject *res;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001958 /* Same as _textiowrapper_decoder_setstate() above. */
Antoine Pitroue4501852009-05-14 18:55:55 +00001959 if (cookie->start_pos == 0 && cookie->dec_flags == 0) {
1960 res = PyObject_CallMethodObjArgs(self->encoder, _PyIO_str_reset, NULL);
1961 self->encoding_start_of_stream = 1;
1962 }
1963 else {
1964 res = PyObject_CallMethodObjArgs(self->encoder, _PyIO_str_setstate,
1965 _PyIO_zero, NULL);
1966 self->encoding_start_of_stream = 0;
1967 }
1968 if (res == NULL)
1969 return -1;
1970 Py_DECREF(res);
1971 return 0;
1972}
1973
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001974static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001975textiowrapper_seek(textio *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001976{
1977 PyObject *cookieObj, *posobj;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001978 cookie_type cookie;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001979 int whence = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001980 PyObject *res;
1981 int cmp;
1982
1983 CHECK_INITIALIZED(self);
1984
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001985 if (!PyArg_ParseTuple(args, "O|i:seek", &cookieObj, &whence))
1986 return NULL;
1987 CHECK_CLOSED(self);
1988
1989 Py_INCREF(cookieObj);
1990
1991 if (!self->seekable) {
Antoine Pitrou0d739d72010-09-05 23:01:12 +00001992 _unsupported("underlying stream is not seekable");
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001993 goto fail;
1994 }
1995
1996 if (whence == 1) {
1997 /* seek relative to current position */
Antoine Pitroue4501852009-05-14 18:55:55 +00001998 cmp = PyObject_RichCompareBool(cookieObj, _PyIO_zero, Py_EQ);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001999 if (cmp < 0)
2000 goto fail;
2001
2002 if (cmp == 0) {
Antoine Pitrou0d739d72010-09-05 23:01:12 +00002003 _unsupported("can't do nonzero cur-relative seeks");
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002004 goto fail;
2005 }
2006
2007 /* Seeking to the current position should attempt to
2008 * sync the underlying buffer with the current position.
2009 */
2010 Py_DECREF(cookieObj);
2011 cookieObj = PyObject_CallMethod((PyObject *)self, "tell", NULL);
2012 if (cookieObj == NULL)
2013 goto fail;
2014 }
2015 else if (whence == 2) {
2016 /* seek relative to end of file */
2017
Antoine Pitroue4501852009-05-14 18:55:55 +00002018 cmp = PyObject_RichCompareBool(cookieObj, _PyIO_zero, Py_EQ);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002019 if (cmp < 0)
2020 goto fail;
2021
2022 if (cmp == 0) {
Antoine Pitrou0d739d72010-09-05 23:01:12 +00002023 _unsupported("can't do nonzero end-relative seeks");
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002024 goto fail;
2025 }
2026
2027 res = PyObject_CallMethod((PyObject *)self, "flush", NULL);
2028 if (res == NULL)
2029 goto fail;
2030 Py_DECREF(res);
2031
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002032 textiowrapper_set_decoded_chars(self, NULL);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002033 Py_CLEAR(self->snapshot);
2034 if (self->decoder) {
2035 res = PyObject_CallMethod(self->decoder, "reset", NULL);
2036 if (res == NULL)
2037 goto fail;
2038 Py_DECREF(res);
2039 }
2040
2041 res = PyObject_CallMethod(self->buffer, "seek", "ii", 0, 2);
2042 Py_XDECREF(cookieObj);
2043 return res;
2044 }
2045 else if (whence != 0) {
2046 PyErr_Format(PyExc_ValueError,
2047 "invalid whence (%d, should be 0, 1 or 2)", whence);
2048 goto fail;
2049 }
2050
Antoine Pitroue4501852009-05-14 18:55:55 +00002051 cmp = PyObject_RichCompareBool(cookieObj, _PyIO_zero, Py_LT);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002052 if (cmp < 0)
2053 goto fail;
2054
2055 if (cmp == 1) {
2056 PyErr_Format(PyExc_ValueError,
2057 "negative seek position %R", cookieObj);
2058 goto fail;
2059 }
2060
2061 res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);
2062 if (res == NULL)
2063 goto fail;
2064 Py_DECREF(res);
2065
2066 /* The strategy of seek() is to go back to the safe start point
2067 * and replay the effect of read(chars_to_skip) from there.
2068 */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002069 if (textiowrapper_parse_cookie(&cookie, cookieObj) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002070 goto fail;
2071
2072 /* Seek back to the safe start point. */
2073 posobj = PyLong_FromOff_t(cookie.start_pos);
2074 if (posobj == NULL)
2075 goto fail;
2076 res = PyObject_CallMethodObjArgs(self->buffer,
2077 _PyIO_str_seek, posobj, NULL);
2078 Py_DECREF(posobj);
2079 if (res == NULL)
2080 goto fail;
2081 Py_DECREF(res);
2082
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002083 textiowrapper_set_decoded_chars(self, NULL);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002084 Py_CLEAR(self->snapshot);
2085
2086 /* Restore the decoder to its state from the safe start point. */
2087 if (self->decoder) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002088 if (_textiowrapper_decoder_setstate(self, &cookie) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002089 goto fail;
2090 }
2091
2092 if (cookie.chars_to_skip) {
2093 /* Just like _read_chunk, feed the decoder and save a snapshot. */
2094 PyObject *input_chunk = PyObject_CallMethod(
2095 self->buffer, "read", "i", cookie.bytes_to_feed);
2096 PyObject *decoded;
2097
2098 if (input_chunk == NULL)
2099 goto fail;
2100
2101 assert (PyBytes_Check(input_chunk));
2102
2103 self->snapshot = Py_BuildValue("iN", cookie.dec_flags, input_chunk);
2104 if (self->snapshot == NULL) {
2105 Py_DECREF(input_chunk);
2106 goto fail;
2107 }
2108
2109 decoded = PyObject_CallMethod(self->decoder, "decode",
2110 "Oi", input_chunk, (int)cookie.need_eof);
2111
2112 if (decoded == NULL)
2113 goto fail;
2114
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002115 textiowrapper_set_decoded_chars(self, decoded);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002116
2117 /* Skip chars_to_skip of the decoded characters. */
2118 if (PyUnicode_GetSize(self->decoded_chars) < cookie.chars_to_skip) {
2119 PyErr_SetString(PyExc_IOError, "can't restore logical file position");
2120 goto fail;
2121 }
2122 self->decoded_chars_used = cookie.chars_to_skip;
2123 }
2124 else {
2125 self->snapshot = Py_BuildValue("iy", cookie.dec_flags, "");
2126 if (self->snapshot == NULL)
2127 goto fail;
2128 }
2129
Antoine Pitroue4501852009-05-14 18:55:55 +00002130 /* Finally, reset the encoder (merely useful for proper BOM handling) */
2131 if (self->encoder) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002132 if (_textiowrapper_encoder_setstate(self, &cookie) < 0)
Antoine Pitroue4501852009-05-14 18:55:55 +00002133 goto fail;
2134 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002135 return cookieObj;
2136 fail:
2137 Py_XDECREF(cookieObj);
2138 return NULL;
2139
2140}
2141
2142static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002143textiowrapper_tell(textio *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002144{
2145 PyObject *res;
2146 PyObject *posobj = NULL;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002147 cookie_type cookie = {0,0,0,0,0};
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002148 PyObject *next_input;
2149 Py_ssize_t chars_to_skip, chars_decoded;
2150 PyObject *saved_state = NULL;
2151 char *input, *input_end;
2152
2153 CHECK_INITIALIZED(self);
2154 CHECK_CLOSED(self);
2155
2156 if (!self->seekable) {
Antoine Pitrou0d739d72010-09-05 23:01:12 +00002157 _unsupported("underlying stream is not seekable");
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002158 goto fail;
2159 }
2160 if (!self->telling) {
2161 PyErr_SetString(PyExc_IOError,
2162 "telling position disabled by next() call");
2163 goto fail;
2164 }
2165
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002166 if (_textiowrapper_writeflush(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002167 return NULL;
2168 res = PyObject_CallMethod((PyObject *)self, "flush", NULL);
2169 if (res == NULL)
2170 goto fail;
2171 Py_DECREF(res);
2172
2173 posobj = PyObject_CallMethod(self->buffer, "tell", NULL);
2174 if (posobj == NULL)
2175 goto fail;
2176
2177 if (self->decoder == NULL || self->snapshot == NULL) {
2178 assert (self->decoded_chars == NULL || PyUnicode_GetSize(self->decoded_chars) == 0);
2179 return posobj;
2180 }
2181
2182#if defined(HAVE_LARGEFILE_SUPPORT)
2183 cookie.start_pos = PyLong_AsLongLong(posobj);
2184#else
2185 cookie.start_pos = PyLong_AsLong(posobj);
2186#endif
2187 if (PyErr_Occurred())
2188 goto fail;
2189
2190 /* Skip backward to the snapshot point (see _read_chunk). */
2191 if (!PyArg_Parse(self->snapshot, "(iO)", &cookie.dec_flags, &next_input))
2192 goto fail;
2193
2194 assert (PyBytes_Check(next_input));
2195
2196 cookie.start_pos -= PyBytes_GET_SIZE(next_input);
2197
2198 /* How many decoded characters have been used up since the snapshot? */
2199 if (self->decoded_chars_used == 0) {
2200 /* We haven't moved from the snapshot point. */
2201 Py_DECREF(posobj);
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002202 return textiowrapper_build_cookie(&cookie);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002203 }
2204
2205 chars_to_skip = self->decoded_chars_used;
2206
2207 /* Starting from the snapshot position, we will walk the decoder
2208 * forward until it gives us enough decoded characters.
2209 */
2210 saved_state = PyObject_CallMethodObjArgs(self->decoder,
2211 _PyIO_str_getstate, NULL);
2212 if (saved_state == NULL)
2213 goto fail;
2214
2215 /* Note our initial start point. */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002216 if (_textiowrapper_decoder_setstate(self, &cookie) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002217 goto fail;
2218
2219 /* Feed the decoder one byte at a time. As we go, note the
2220 * nearest "safe start point" before the current location
2221 * (a point where the decoder has nothing buffered, so seek()
2222 * can safely start from there and advance to this location).
2223 */
2224 chars_decoded = 0;
2225 input = PyBytes_AS_STRING(next_input);
2226 input_end = input + PyBytes_GET_SIZE(next_input);
2227 while (input < input_end) {
2228 PyObject *state;
2229 char *dec_buffer;
2230 Py_ssize_t dec_buffer_len;
2231 int dec_flags;
2232
2233 PyObject *decoded = PyObject_CallMethod(
2234 self->decoder, "decode", "y#", input, 1);
2235 if (decoded == NULL)
2236 goto fail;
2237 assert (PyUnicode_Check(decoded));
2238 chars_decoded += PyUnicode_GET_SIZE(decoded);
2239 Py_DECREF(decoded);
2240
2241 cookie.bytes_to_feed += 1;
2242
2243 state = PyObject_CallMethodObjArgs(self->decoder,
2244 _PyIO_str_getstate, NULL);
2245 if (state == NULL)
2246 goto fail;
2247 if (!PyArg_Parse(state, "(y#i)", &dec_buffer, &dec_buffer_len, &dec_flags)) {
2248 Py_DECREF(state);
2249 goto fail;
2250 }
2251 Py_DECREF(state);
2252
2253 if (dec_buffer_len == 0 && chars_decoded <= chars_to_skip) {
2254 /* Decoder buffer is empty, so this is a safe start point. */
2255 cookie.start_pos += cookie.bytes_to_feed;
2256 chars_to_skip -= chars_decoded;
2257 cookie.dec_flags = dec_flags;
2258 cookie.bytes_to_feed = 0;
2259 chars_decoded = 0;
2260 }
2261 if (chars_decoded >= chars_to_skip)
2262 break;
2263 input++;
2264 }
2265 if (input == input_end) {
2266 /* We didn't get enough decoded data; signal EOF to get more. */
2267 PyObject *decoded = PyObject_CallMethod(
2268 self->decoder, "decode", "yi", "", /* final = */ 1);
2269 if (decoded == NULL)
2270 goto fail;
2271 assert (PyUnicode_Check(decoded));
2272 chars_decoded += PyUnicode_GET_SIZE(decoded);
2273 Py_DECREF(decoded);
2274 cookie.need_eof = 1;
2275
2276 if (chars_decoded < chars_to_skip) {
2277 PyErr_SetString(PyExc_IOError,
2278 "can't reconstruct logical file position");
2279 goto fail;
2280 }
2281 }
2282
2283 /* finally */
2284 Py_XDECREF(posobj);
2285 res = PyObject_CallMethod(self->decoder, "setstate", "(O)", saved_state);
2286 Py_DECREF(saved_state);
2287 if (res == NULL)
2288 return NULL;
2289 Py_DECREF(res);
2290
2291 /* The returned cookie corresponds to the last safe start point. */
2292 cookie.chars_to_skip = Py_SAFE_DOWNCAST(chars_to_skip, Py_ssize_t, int);
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002293 return textiowrapper_build_cookie(&cookie);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002294
2295 fail:
2296 Py_XDECREF(posobj);
2297 if (saved_state) {
2298 PyObject *type, *value, *traceback;
2299 PyErr_Fetch(&type, &value, &traceback);
2300
2301 res = PyObject_CallMethod(self->decoder, "setstate", "(O)", saved_state);
2302 Py_DECREF(saved_state);
2303 if (res == NULL)
2304 return NULL;
2305 Py_DECREF(res);
2306
2307 PyErr_Restore(type, value, traceback);
2308 }
2309 return NULL;
2310}
2311
2312static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002313textiowrapper_truncate(textio *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002314{
2315 PyObject *pos = Py_None;
2316 PyObject *res;
2317
2318 CHECK_INITIALIZED(self)
2319 if (!PyArg_ParseTuple(args, "|O:truncate", &pos)) {
2320 return NULL;
2321 }
2322
2323 res = PyObject_CallMethodObjArgs((PyObject *) self, _PyIO_str_flush, NULL);
2324 if (res == NULL)
2325 return NULL;
2326 Py_DECREF(res);
2327
Antoine Pitrou905a2ff2010-01-31 22:47:27 +00002328 return PyObject_CallMethodObjArgs(self->buffer, _PyIO_str_truncate, pos, NULL);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002329}
2330
Benjamin Petersonc4c0eae2009-03-09 00:07:03 +00002331static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002332textiowrapper_repr(textio *self)
Benjamin Petersonc4c0eae2009-03-09 00:07:03 +00002333{
Antoine Pitroua4815ca2011-01-09 20:38:15 +00002334 PyObject *nameobj, *modeobj, *res, *s;
Antoine Pitrou716c4442009-05-23 19:04:03 +00002335
2336 CHECK_INITIALIZED(self);
2337
Antoine Pitroua4815ca2011-01-09 20:38:15 +00002338 res = PyUnicode_FromString("<_io.TextIOWrapper");
2339 if (res == NULL)
2340 return NULL;
Antoine Pitrou716c4442009-05-23 19:04:03 +00002341 nameobj = PyObject_GetAttrString((PyObject *) self, "name");
2342 if (nameobj == NULL) {
2343 if (PyErr_ExceptionMatches(PyExc_AttributeError))
2344 PyErr_Clear();
2345 else
Antoine Pitroua4815ca2011-01-09 20:38:15 +00002346 goto error;
Antoine Pitrou716c4442009-05-23 19:04:03 +00002347 }
2348 else {
Antoine Pitroua4815ca2011-01-09 20:38:15 +00002349 s = PyUnicode_FromFormat(" name=%R", nameobj);
Antoine Pitrou716c4442009-05-23 19:04:03 +00002350 Py_DECREF(nameobj);
Antoine Pitroua4815ca2011-01-09 20:38:15 +00002351 if (s == NULL)
2352 goto error;
2353 PyUnicode_AppendAndDel(&res, s);
2354 if (res == NULL)
2355 return NULL;
Antoine Pitrou716c4442009-05-23 19:04:03 +00002356 }
Antoine Pitroua4815ca2011-01-09 20:38:15 +00002357 modeobj = PyObject_GetAttrString((PyObject *) self, "mode");
2358 if (modeobj == NULL) {
2359 if (PyErr_ExceptionMatches(PyExc_AttributeError))
2360 PyErr_Clear();
2361 else
2362 goto error;
2363 }
2364 else {
2365 s = PyUnicode_FromFormat(" mode=%R", modeobj);
2366 Py_DECREF(modeobj);
2367 if (s == NULL)
2368 goto error;
2369 PyUnicode_AppendAndDel(&res, s);
2370 if (res == NULL)
2371 return NULL;
2372 }
2373 s = PyUnicode_FromFormat("%U encoding=%R>",
2374 res, self->encoding);
2375 Py_DECREF(res);
2376 return s;
2377error:
2378 Py_XDECREF(res);
2379 return NULL;
Benjamin Petersonc4c0eae2009-03-09 00:07:03 +00002380}
2381
2382
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002383/* Inquiries */
2384
2385static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002386textiowrapper_fileno(textio *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002387{
2388 CHECK_INITIALIZED(self);
2389 return PyObject_CallMethod(self->buffer, "fileno", NULL);
2390}
2391
2392static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002393textiowrapper_seekable(textio *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002394{
2395 CHECK_INITIALIZED(self);
2396 return PyObject_CallMethod(self->buffer, "seekable", NULL);
2397}
2398
2399static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002400textiowrapper_readable(textio *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002401{
2402 CHECK_INITIALIZED(self);
2403 return PyObject_CallMethod(self->buffer, "readable", NULL);
2404}
2405
2406static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002407textiowrapper_writable(textio *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002408{
2409 CHECK_INITIALIZED(self);
2410 return PyObject_CallMethod(self->buffer, "writable", NULL);
2411}
2412
2413static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002414textiowrapper_isatty(textio *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002415{
2416 CHECK_INITIALIZED(self);
2417 return PyObject_CallMethod(self->buffer, "isatty", NULL);
2418}
2419
2420static PyObject *
Antoine Pitrou243757e2010-11-05 21:15:39 +00002421textiowrapper_getstate(textio *self, PyObject *args)
2422{
2423 PyErr_Format(PyExc_TypeError,
2424 "cannot serialize '%s' object", Py_TYPE(self)->tp_name);
2425 return NULL;
2426}
2427
2428static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002429textiowrapper_flush(textio *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002430{
2431 CHECK_INITIALIZED(self);
2432 CHECK_CLOSED(self);
2433 self->telling = self->seekable;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002434 if (_textiowrapper_writeflush(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002435 return NULL;
2436 return PyObject_CallMethod(self->buffer, "flush", NULL);
2437}
2438
2439static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002440textiowrapper_close(textio *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002441{
2442 PyObject *res;
Antoine Pitrou6be88762010-05-03 16:48:20 +00002443 int r;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002444 CHECK_INITIALIZED(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002445
Antoine Pitrou6be88762010-05-03 16:48:20 +00002446 res = textiowrapper_closed_get(self, NULL);
2447 if (res == NULL)
2448 return NULL;
2449 r = PyObject_IsTrue(res);
2450 Py_DECREF(res);
2451 if (r < 0)
2452 return NULL;
Victor Stinnerf6c57832010-05-19 01:17:01 +00002453
Antoine Pitrou6be88762010-05-03 16:48:20 +00002454 if (r > 0) {
2455 Py_RETURN_NONE; /* stream already closed */
2456 }
2457 else {
Antoine Pitroue033e062010-10-29 10:38:18 +00002458 if (self->deallocating) {
2459 res = PyObject_CallMethod(self->buffer, "_dealloc_warn", "O", self);
2460 if (res)
2461 Py_DECREF(res);
2462 else
2463 PyErr_Clear();
2464 }
Antoine Pitrou6be88762010-05-03 16:48:20 +00002465 res = PyObject_CallMethod((PyObject *)self, "flush", NULL);
2466 if (res == NULL) {
2467 return NULL;
2468 }
2469 else
2470 Py_DECREF(res);
2471
2472 return PyObject_CallMethod(self->buffer, "close", NULL);
2473 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002474}
2475
2476static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002477textiowrapper_iternext(textio *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002478{
2479 PyObject *line;
2480
2481 CHECK_INITIALIZED(self);
2482
2483 self->telling = 0;
2484 if (Py_TYPE(self) == &PyTextIOWrapper_Type) {
2485 /* Skip method call overhead for speed */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002486 line = _textiowrapper_readline(self, -1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002487 }
2488 else {
2489 line = PyObject_CallMethodObjArgs((PyObject *)self,
2490 _PyIO_str_readline, NULL);
2491 if (line && !PyUnicode_Check(line)) {
2492 PyErr_Format(PyExc_IOError,
2493 "readline() should have returned an str object, "
2494 "not '%.200s'", Py_TYPE(line)->tp_name);
2495 Py_DECREF(line);
2496 return NULL;
2497 }
2498 }
2499
2500 if (line == NULL)
2501 return NULL;
2502
2503 if (PyUnicode_GET_SIZE(line) == 0) {
2504 /* Reached EOF or would have blocked */
2505 Py_DECREF(line);
2506 Py_CLEAR(self->snapshot);
2507 self->telling = self->seekable;
2508 return NULL;
2509 }
2510
2511 return line;
2512}
2513
2514static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002515textiowrapper_name_get(textio *self, void *context)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002516{
2517 CHECK_INITIALIZED(self);
2518 return PyObject_GetAttrString(self->buffer, "name");
2519}
2520
2521static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002522textiowrapper_closed_get(textio *self, void *context)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002523{
2524 CHECK_INITIALIZED(self);
2525 return PyObject_GetAttr(self->buffer, _PyIO_str_closed);
2526}
2527
2528static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002529textiowrapper_newlines_get(textio *self, void *context)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002530{
2531 PyObject *res;
2532 CHECK_INITIALIZED(self);
2533 if (self->decoder == NULL)
2534 Py_RETURN_NONE;
2535 res = PyObject_GetAttr(self->decoder, _PyIO_str_newlines);
2536 if (res == NULL) {
Benjamin Peterson2cfca792009-06-06 20:46:48 +00002537 if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
2538 PyErr_Clear();
2539 Py_RETURN_NONE;
2540 }
2541 else {
2542 return NULL;
2543 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002544 }
2545 return res;
2546}
2547
2548static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002549textiowrapper_errors_get(textio *self, void *context)
Benjamin Peterson0926ad12009-06-06 18:02:12 +00002550{
2551 CHECK_INITIALIZED(self);
2552 return PyUnicode_FromString(PyBytes_AS_STRING(self->errors));
2553}
2554
2555static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002556textiowrapper_chunk_size_get(textio *self, void *context)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002557{
2558 CHECK_INITIALIZED(self);
2559 return PyLong_FromSsize_t(self->chunk_size);
2560}
2561
2562static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002563textiowrapper_chunk_size_set(textio *self, PyObject *arg, void *context)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002564{
2565 Py_ssize_t n;
2566 CHECK_INITIALIZED_INT(self);
Antoine Pitroucb4ae812011-07-13 21:07:49 +02002567 n = PyNumber_AsSsize_t(arg, PyExc_ValueError);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002568 if (n == -1 && PyErr_Occurred())
2569 return -1;
2570 if (n <= 0) {
2571 PyErr_SetString(PyExc_ValueError,
2572 "a strictly positive integer is required");
2573 return -1;
2574 }
2575 self->chunk_size = n;
2576 return 0;
2577}
2578
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002579static PyMethodDef textiowrapper_methods[] = {
2580 {"detach", (PyCFunction)textiowrapper_detach, METH_NOARGS},
2581 {"write", (PyCFunction)textiowrapper_write, METH_VARARGS},
2582 {"read", (PyCFunction)textiowrapper_read, METH_VARARGS},
2583 {"readline", (PyCFunction)textiowrapper_readline, METH_VARARGS},
2584 {"flush", (PyCFunction)textiowrapper_flush, METH_NOARGS},
2585 {"close", (PyCFunction)textiowrapper_close, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002586
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002587 {"fileno", (PyCFunction)textiowrapper_fileno, METH_NOARGS},
2588 {"seekable", (PyCFunction)textiowrapper_seekable, METH_NOARGS},
2589 {"readable", (PyCFunction)textiowrapper_readable, METH_NOARGS},
2590 {"writable", (PyCFunction)textiowrapper_writable, METH_NOARGS},
2591 {"isatty", (PyCFunction)textiowrapper_isatty, METH_NOARGS},
Antoine Pitrou243757e2010-11-05 21:15:39 +00002592 {"__getstate__", (PyCFunction)textiowrapper_getstate, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002593
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002594 {"seek", (PyCFunction)textiowrapper_seek, METH_VARARGS},
2595 {"tell", (PyCFunction)textiowrapper_tell, METH_NOARGS},
2596 {"truncate", (PyCFunction)textiowrapper_truncate, METH_VARARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002597 {NULL, NULL}
2598};
2599
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002600static PyMemberDef textiowrapper_members[] = {
2601 {"encoding", T_OBJECT, offsetof(textio, encoding), READONLY},
2602 {"buffer", T_OBJECT, offsetof(textio, buffer), READONLY},
2603 {"line_buffering", T_BOOL, offsetof(textio, line_buffering), READONLY},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002604 {NULL}
2605};
2606
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002607static PyGetSetDef textiowrapper_getset[] = {
2608 {"name", (getter)textiowrapper_name_get, NULL, NULL},
2609 {"closed", (getter)textiowrapper_closed_get, NULL, NULL},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002610/* {"mode", (getter)TextIOWrapper_mode_get, NULL, NULL},
2611*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002612 {"newlines", (getter)textiowrapper_newlines_get, NULL, NULL},
2613 {"errors", (getter)textiowrapper_errors_get, NULL, NULL},
2614 {"_CHUNK_SIZE", (getter)textiowrapper_chunk_size_get,
2615 (setter)textiowrapper_chunk_size_set, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00002616 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002617};
2618
2619PyTypeObject PyTextIOWrapper_Type = {
2620 PyVarObject_HEAD_INIT(NULL, 0)
2621 "_io.TextIOWrapper", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002622 sizeof(textio), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002623 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002624 (destructor)textiowrapper_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002625 0, /*tp_print*/
2626 0, /*tp_getattr*/
Benjamin Petersonc4c0eae2009-03-09 00:07:03 +00002627 0, /*tps_etattr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002628 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002629 (reprfunc)textiowrapper_repr,/*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002630 0, /*tp_as_number*/
2631 0, /*tp_as_sequence*/
2632 0, /*tp_as_mapping*/
2633 0, /*tp_hash */
2634 0, /*tp_call*/
2635 0, /*tp_str*/
2636 0, /*tp_getattro*/
2637 0, /*tp_setattro*/
2638 0, /*tp_as_buffer*/
2639 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2640 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002641 textiowrapper_doc, /* tp_doc */
2642 (traverseproc)textiowrapper_traverse, /* tp_traverse */
2643 (inquiry)textiowrapper_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002644 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002645 offsetof(textio, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002646 0, /* tp_iter */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002647 (iternextfunc)textiowrapper_iternext, /* tp_iternext */
2648 textiowrapper_methods, /* tp_methods */
2649 textiowrapper_members, /* tp_members */
2650 textiowrapper_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002651 0, /* tp_base */
2652 0, /* tp_dict */
2653 0, /* tp_descr_get */
2654 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002655 offsetof(textio, dict), /*tp_dictoffset*/
2656 (initproc)textiowrapper_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002657 0, /* tp_alloc */
2658 PyType_GenericNew, /* tp_new */
2659};