blob: 70d062b16f13c1769facfff79d3295e75b958690 [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;
656 char readuniversal;
657 char readtranslate;
658 char writetranslate;
659 char seekable;
660 char telling;
Antoine Pitroue033e062010-10-29 10:38:18 +0000661 char deallocating;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000662 /* Specialized encoding func (see below) */
663 encodefunc_t encodefunc;
Antoine Pitroue4501852009-05-14 18:55:55 +0000664 /* Whether or not it's the start of the stream */
665 char encoding_start_of_stream;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000666
667 /* Reads and writes are internally buffered in order to speed things up.
668 However, any read will first flush the write buffer if itsn't empty.
Antoine Pitrou24f36292009-03-28 22:16:42 +0000669
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000670 Please also note that text to be written is first encoded before being
671 buffered. This is necessary so that encoding errors are immediately
672 reported to the caller, but it unfortunately means that the
673 IncrementalEncoder (whose encode() method is always written in Python)
674 becomes a bottleneck for small writes.
675 */
676 PyObject *decoded_chars; /* buffer for text returned from decoder */
677 Py_ssize_t decoded_chars_used; /* offset into _decoded_chars for read() */
678 PyObject *pending_bytes; /* list of bytes objects waiting to be
679 written, or NULL */
680 Py_ssize_t pending_bytes_count;
Antoine Pitrou211b81d2011-02-25 20:27:33 +0000681
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000682 /* snapshot is either None, or a tuple (dec_flags, next_input) where
683 * dec_flags is the second (integer) item of the decoder state and
684 * next_input is the chunk of input bytes that comes next after the
685 * snapshot point. We use this to reconstruct decoder states in tell().
686 */
Antoine Pitrou211b81d2011-02-25 20:27:33 +0000687 PyObject *snapshot;
688 /* Bytes-to-characters ratio for the current chunk. Serves as input for
689 the heuristic in tell(). */
690 double b2cratio;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000691
692 /* Cache raw object if it's a FileIO object */
693 PyObject *raw;
694
695 PyObject *weakreflist;
696 PyObject *dict;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000697} textio;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000698
699
700/* A couple of specialized cases in order to bypass the slow incremental
701 encoding methods for the most popular encodings. */
702
703static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000704ascii_encode(textio *self, PyObject *text)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000705{
706 return PyUnicode_EncodeASCII(PyUnicode_AS_UNICODE(text),
707 PyUnicode_GET_SIZE(text),
708 PyBytes_AS_STRING(self->errors));
709}
710
711static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000712utf16be_encode(textio *self, PyObject *text)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000713{
714 return PyUnicode_EncodeUTF16(PyUnicode_AS_UNICODE(text),
715 PyUnicode_GET_SIZE(text),
716 PyBytes_AS_STRING(self->errors), 1);
717}
718
719static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000720utf16le_encode(textio *self, PyObject *text)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000721{
722 return PyUnicode_EncodeUTF16(PyUnicode_AS_UNICODE(text),
723 PyUnicode_GET_SIZE(text),
724 PyBytes_AS_STRING(self->errors), -1);
725}
726
727static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000728utf16_encode(textio *self, PyObject *text)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000729{
Antoine Pitroue4501852009-05-14 18:55:55 +0000730 if (!self->encoding_start_of_stream) {
731 /* Skip the BOM and use native byte ordering */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000732#if defined(WORDS_BIGENDIAN)
Antoine Pitroue4501852009-05-14 18:55:55 +0000733 return utf16be_encode(self, text);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000734#else
Antoine Pitroue4501852009-05-14 18:55:55 +0000735 return utf16le_encode(self, text);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000736#endif
Antoine Pitroue4501852009-05-14 18:55:55 +0000737 }
738 return PyUnicode_EncodeUTF16(PyUnicode_AS_UNICODE(text),
739 PyUnicode_GET_SIZE(text),
740 PyBytes_AS_STRING(self->errors), 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000741}
742
Antoine Pitroue4501852009-05-14 18:55:55 +0000743static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000744utf32be_encode(textio *self, PyObject *text)
Antoine Pitroue4501852009-05-14 18:55:55 +0000745{
746 return PyUnicode_EncodeUTF32(PyUnicode_AS_UNICODE(text),
747 PyUnicode_GET_SIZE(text),
748 PyBytes_AS_STRING(self->errors), 1);
749}
750
751static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000752utf32le_encode(textio *self, PyObject *text)
Antoine Pitroue4501852009-05-14 18:55:55 +0000753{
754 return PyUnicode_EncodeUTF32(PyUnicode_AS_UNICODE(text),
755 PyUnicode_GET_SIZE(text),
756 PyBytes_AS_STRING(self->errors), -1);
757}
758
759static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000760utf32_encode(textio *self, PyObject *text)
Antoine Pitroue4501852009-05-14 18:55:55 +0000761{
762 if (!self->encoding_start_of_stream) {
763 /* Skip the BOM and use native byte ordering */
764#if defined(WORDS_BIGENDIAN)
765 return utf32be_encode(self, text);
766#else
767 return utf32le_encode(self, text);
768#endif
769 }
770 return PyUnicode_EncodeUTF32(PyUnicode_AS_UNICODE(text),
771 PyUnicode_GET_SIZE(text),
772 PyBytes_AS_STRING(self->errors), 0);
773}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000774
775static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000776utf8_encode(textio *self, PyObject *text)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000777{
778 return PyUnicode_EncodeUTF8(PyUnicode_AS_UNICODE(text),
779 PyUnicode_GET_SIZE(text),
780 PyBytes_AS_STRING(self->errors));
781}
782
783static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000784latin1_encode(textio *self, PyObject *text)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000785{
786 return PyUnicode_EncodeLatin1(PyUnicode_AS_UNICODE(text),
787 PyUnicode_GET_SIZE(text),
788 PyBytes_AS_STRING(self->errors));
789}
790
791/* Map normalized encoding names onto the specialized encoding funcs */
792
793typedef struct {
794 const char *name;
795 encodefunc_t encodefunc;
796} encodefuncentry;
797
Antoine Pitrou24f36292009-03-28 22:16:42 +0000798static encodefuncentry encodefuncs[] = {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000799 {"ascii", (encodefunc_t) ascii_encode},
800 {"iso8859-1", (encodefunc_t) latin1_encode},
Antoine Pitroue4501852009-05-14 18:55:55 +0000801 {"utf-8", (encodefunc_t) utf8_encode},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000802 {"utf-16-be", (encodefunc_t) utf16be_encode},
803 {"utf-16-le", (encodefunc_t) utf16le_encode},
804 {"utf-16", (encodefunc_t) utf16_encode},
Antoine Pitroue4501852009-05-14 18:55:55 +0000805 {"utf-32-be", (encodefunc_t) utf32be_encode},
806 {"utf-32-le", (encodefunc_t) utf32le_encode},
807 {"utf-32", (encodefunc_t) utf32_encode},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000808 {NULL, NULL}
809};
810
811
812static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +0000813textiowrapper_init(textio *self, PyObject *args, PyObject *kwds)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000814{
815 char *kwlist[] = {"buffer", "encoding", "errors",
816 "newline", "line_buffering",
817 NULL};
818 PyObject *buffer, *raw;
819 char *encoding = NULL;
820 char *errors = NULL;
821 char *newline = NULL;
822 int line_buffering = 0;
823 _PyIO_State *state = IO_STATE;
824
825 PyObject *res;
826 int r;
827
828 self->ok = 0;
Benjamin Petersond2e0c792009-05-01 20:40:59 +0000829 self->detached = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000830 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|zzzi:fileio",
831 kwlist, &buffer, &encoding, &errors,
832 &newline, &line_buffering))
833 return -1;
834
835 if (newline && newline[0] != '\0'
836 && !(newline[0] == '\n' && newline[1] == '\0')
837 && !(newline[0] == '\r' && newline[1] == '\0')
838 && !(newline[0] == '\r' && newline[1] == '\n' && newline[2] == '\0')) {
839 PyErr_Format(PyExc_ValueError,
840 "illegal newline value: %s", newline);
841 return -1;
842 }
843
844 Py_CLEAR(self->buffer);
845 Py_CLEAR(self->encoding);
846 Py_CLEAR(self->encoder);
847 Py_CLEAR(self->decoder);
848 Py_CLEAR(self->readnl);
849 Py_CLEAR(self->decoded_chars);
850 Py_CLEAR(self->pending_bytes);
851 Py_CLEAR(self->snapshot);
852 Py_CLEAR(self->errors);
853 Py_CLEAR(self->raw);
854 self->decoded_chars_used = 0;
855 self->pending_bytes_count = 0;
856 self->encodefunc = NULL;
Antoine Pitrou211b81d2011-02-25 20:27:33 +0000857 self->b2cratio = 0.0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000858
859 if (encoding == NULL) {
860 /* Try os.device_encoding(fileno) */
861 PyObject *fileno;
862 fileno = PyObject_CallMethod(buffer, "fileno", NULL);
863 /* Ignore only AttributeError and UnsupportedOperation */
864 if (fileno == NULL) {
865 if (PyErr_ExceptionMatches(PyExc_AttributeError) ||
866 PyErr_ExceptionMatches(state->unsupported_operation)) {
867 PyErr_Clear();
868 }
869 else {
870 goto error;
871 }
872 }
873 else {
874 self->encoding = PyObject_CallMethod(state->os_module,
875 "device_encoding",
876 "N", fileno);
877 if (self->encoding == NULL)
878 goto error;
879 else if (!PyUnicode_Check(self->encoding))
880 Py_CLEAR(self->encoding);
881 }
882 }
883 if (encoding == NULL && self->encoding == NULL) {
884 if (state->locale_module == NULL) {
885 state->locale_module = PyImport_ImportModule("locale");
886 if (state->locale_module == NULL)
887 goto catch_ImportError;
888 else
889 goto use_locale;
890 }
891 else {
892 use_locale:
893 self->encoding = PyObject_CallMethod(
894 state->locale_module, "getpreferredencoding", NULL);
895 if (self->encoding == NULL) {
896 catch_ImportError:
897 /*
898 Importing locale can raise a ImportError because of
899 _functools, and locale.getpreferredencoding can raise a
900 ImportError if _locale is not available. These will happen
901 during module building.
902 */
903 if (PyErr_ExceptionMatches(PyExc_ImportError)) {
904 PyErr_Clear();
905 self->encoding = PyUnicode_FromString("ascii");
906 }
907 else
908 goto error;
909 }
910 else if (!PyUnicode_Check(self->encoding))
911 Py_CLEAR(self->encoding);
912 }
913 }
Victor Stinnerf6c57832010-05-19 01:17:01 +0000914 if (self->encoding != NULL) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000915 encoding = _PyUnicode_AsString(self->encoding);
Victor Stinnerf6c57832010-05-19 01:17:01 +0000916 if (encoding == NULL)
917 goto error;
918 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000919 else if (encoding != NULL) {
920 self->encoding = PyUnicode_FromString(encoding);
921 if (self->encoding == NULL)
922 goto error;
923 }
924 else {
925 PyErr_SetString(PyExc_IOError,
926 "could not determine default encoding");
927 }
928
929 if (errors == NULL)
930 errors = "strict";
931 self->errors = PyBytes_FromString(errors);
932 if (self->errors == NULL)
933 goto error;
934
935 self->chunk_size = 8192;
936 self->readuniversal = (newline == NULL || newline[0] == '\0');
937 self->line_buffering = line_buffering;
938 self->readtranslate = (newline == NULL);
939 if (newline) {
940 self->readnl = PyUnicode_FromString(newline);
941 if (self->readnl == NULL)
942 return -1;
943 }
944 self->writetranslate = (newline == NULL || newline[0] != '\0');
945 if (!self->readuniversal && self->readnl) {
946 self->writenl = _PyUnicode_AsString(self->readnl);
Victor Stinnerf6c57832010-05-19 01:17:01 +0000947 if (self->writenl == NULL)
948 goto error;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +0000949 if (!strcmp(self->writenl, "\n"))
950 self->writenl = NULL;
951 }
952#ifdef MS_WINDOWS
953 else
954 self->writenl = "\r\n";
955#endif
956
957 /* Build the decoder object */
958 res = PyObject_CallMethod(buffer, "readable", NULL);
959 if (res == NULL)
960 goto error;
961 r = PyObject_IsTrue(res);
962 Py_DECREF(res);
963 if (r == -1)
964 goto error;
965 if (r == 1) {
966 self->decoder = PyCodec_IncrementalDecoder(
967 encoding, errors);
968 if (self->decoder == NULL)
969 goto error;
970
971 if (self->readuniversal) {
972 PyObject *incrementalDecoder = PyObject_CallFunction(
973 (PyObject *)&PyIncrementalNewlineDecoder_Type,
974 "Oi", self->decoder, (int)self->readtranslate);
975 if (incrementalDecoder == NULL)
976 goto error;
977 Py_CLEAR(self->decoder);
978 self->decoder = incrementalDecoder;
979 }
980 }
981
982 /* Build the encoder object */
983 res = PyObject_CallMethod(buffer, "writable", NULL);
984 if (res == NULL)
985 goto error;
986 r = PyObject_IsTrue(res);
987 Py_DECREF(res);
988 if (r == -1)
989 goto error;
990 if (r == 1) {
991 PyObject *ci;
992 self->encoder = PyCodec_IncrementalEncoder(
993 encoding, errors);
994 if (self->encoder == NULL)
995 goto error;
996 /* Get the normalized named of the codec */
997 ci = _PyCodec_Lookup(encoding);
998 if (ci == NULL)
999 goto error;
1000 res = PyObject_GetAttrString(ci, "name");
1001 Py_DECREF(ci);
Benjamin Peterson2cfca792009-06-06 20:46:48 +00001002 if (res == NULL) {
1003 if (PyErr_ExceptionMatches(PyExc_AttributeError))
1004 PyErr_Clear();
1005 else
1006 goto error;
1007 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001008 else if (PyUnicode_Check(res)) {
1009 encodefuncentry *e = encodefuncs;
1010 while (e->name != NULL) {
1011 if (!PyUnicode_CompareWithASCIIString(res, e->name)) {
1012 self->encodefunc = e->encodefunc;
1013 break;
1014 }
1015 e++;
1016 }
1017 }
1018 Py_XDECREF(res);
1019 }
1020
1021 self->buffer = buffer;
1022 Py_INCREF(buffer);
Antoine Pitrou24f36292009-03-28 22:16:42 +00001023
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001024 if (Py_TYPE(buffer) == &PyBufferedReader_Type ||
1025 Py_TYPE(buffer) == &PyBufferedWriter_Type ||
1026 Py_TYPE(buffer) == &PyBufferedRandom_Type) {
1027 raw = PyObject_GetAttrString(buffer, "raw");
1028 /* Cache the raw FileIO object to speed up 'closed' checks */
Benjamin Peterson2cfca792009-06-06 20:46:48 +00001029 if (raw == NULL) {
1030 if (PyErr_ExceptionMatches(PyExc_AttributeError))
1031 PyErr_Clear();
1032 else
1033 goto error;
1034 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001035 else if (Py_TYPE(raw) == &PyFileIO_Type)
1036 self->raw = raw;
1037 else
1038 Py_DECREF(raw);
1039 }
1040
1041 res = PyObject_CallMethod(buffer, "seekable", NULL);
1042 if (res == NULL)
1043 goto error;
1044 self->seekable = self->telling = PyObject_IsTrue(res);
1045 Py_DECREF(res);
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
1290 if (self->line_buffering &&
1291 (haslf ||
1292 findchar(PyUnicode_AS_UNICODE(text),
1293 PyUnicode_GET_SIZE(text), '\r')))
1294 needflush = 1;
1295
1296 /* XXX What if we were just reading? */
Antoine Pitroue4501852009-05-14 18:55:55 +00001297 if (self->encodefunc != NULL) {
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001298 b = (*self->encodefunc)((PyObject *) self, text);
Antoine Pitroue4501852009-05-14 18:55:55 +00001299 self->encoding_start_of_stream = 0;
1300 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001301 else
1302 b = PyObject_CallMethodObjArgs(self->encoder,
1303 _PyIO_str_encode, text, NULL);
1304 Py_DECREF(text);
1305 if (b == NULL)
1306 return NULL;
1307
1308 if (self->pending_bytes == NULL) {
1309 self->pending_bytes = PyList_New(0);
1310 if (self->pending_bytes == NULL) {
1311 Py_DECREF(b);
1312 return NULL;
1313 }
1314 self->pending_bytes_count = 0;
1315 }
1316 if (PyList_Append(self->pending_bytes, b) < 0) {
1317 Py_DECREF(b);
1318 return NULL;
1319 }
1320 self->pending_bytes_count += PyBytes_GET_SIZE(b);
1321 Py_DECREF(b);
1322 if (self->pending_bytes_count > self->chunk_size || needflush) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001323 if (_textiowrapper_writeflush(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001324 return NULL;
1325 }
Antoine Pitrou24f36292009-03-28 22:16:42 +00001326
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001327 if (needflush) {
1328 ret = PyObject_CallMethodObjArgs(self->buffer, _PyIO_str_flush, NULL);
1329 if (ret == NULL)
1330 return NULL;
1331 Py_DECREF(ret);
1332 }
1333
1334 Py_CLEAR(self->snapshot);
1335
1336 if (self->decoder) {
1337 ret = PyObject_CallMethod(self->decoder, "reset", NULL);
1338 if (ret == NULL)
1339 return NULL;
1340 Py_DECREF(ret);
1341 }
1342
1343 return PyLong_FromSsize_t(textlen);
1344}
1345
1346/* Steal a reference to chars and store it in the decoded_char buffer;
1347 */
1348static void
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001349textiowrapper_set_decoded_chars(textio *self, PyObject *chars)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001350{
1351 Py_CLEAR(self->decoded_chars);
1352 self->decoded_chars = chars;
1353 self->decoded_chars_used = 0;
1354}
1355
1356static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001357textiowrapper_get_decoded_chars(textio *self, Py_ssize_t n)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001358{
1359 PyObject *chars;
1360 Py_ssize_t avail;
1361
1362 if (self->decoded_chars == NULL)
1363 return PyUnicode_FromStringAndSize(NULL, 0);
1364
1365 avail = (PyUnicode_GET_SIZE(self->decoded_chars)
1366 - self->decoded_chars_used);
1367
1368 assert(avail >= 0);
1369
1370 if (n < 0 || n > avail)
1371 n = avail;
1372
1373 if (self->decoded_chars_used > 0 || n < avail) {
1374 chars = PyUnicode_FromUnicode(
1375 PyUnicode_AS_UNICODE(self->decoded_chars)
1376 + self->decoded_chars_used, n);
1377 if (chars == NULL)
1378 return NULL;
1379 }
1380 else {
1381 chars = self->decoded_chars;
1382 Py_INCREF(chars);
1383 }
1384
1385 self->decoded_chars_used += n;
1386 return chars;
1387}
1388
1389/* Read and decode the next chunk of data from the BufferedReader.
1390 */
1391static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001392textiowrapper_read_chunk(textio *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001393{
1394 PyObject *dec_buffer = NULL;
1395 PyObject *dec_flags = NULL;
1396 PyObject *input_chunk = NULL;
1397 PyObject *decoded_chars, *chunk_size;
Antoine Pitrou211b81d2011-02-25 20:27:33 +00001398 Py_ssize_t nbytes, nchars;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001399 int eof;
1400
1401 /* The return value is True unless EOF was reached. The decoded string is
1402 * placed in self._decoded_chars (replacing its previous value). The
1403 * entire input chunk is sent to the decoder, though some of it may remain
1404 * buffered in the decoder, yet to be converted.
1405 */
1406
1407 if (self->decoder == NULL) {
Antoine Pitrou0d739d72010-09-05 23:01:12 +00001408 _unsupported("not readable");
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001409 return -1;
1410 }
1411
1412 if (self->telling) {
1413 /* To prepare for tell(), we need to snapshot a point in the file
1414 * where the decoder's input buffer is empty.
1415 */
1416
1417 PyObject *state = PyObject_CallMethodObjArgs(self->decoder,
1418 _PyIO_str_getstate, NULL);
1419 if (state == NULL)
1420 return -1;
1421 /* Given this, we know there was a valid snapshot point
1422 * len(dec_buffer) bytes ago with decoder state (b'', dec_flags).
1423 */
1424 if (PyArg_Parse(state, "(OO)", &dec_buffer, &dec_flags) < 0) {
1425 Py_DECREF(state);
1426 return -1;
1427 }
1428 Py_INCREF(dec_buffer);
1429 Py_INCREF(dec_flags);
1430 Py_DECREF(state);
1431 }
1432
1433 /* Read a chunk, decode it, and put the result in self._decoded_chars. */
1434 chunk_size = PyLong_FromSsize_t(self->chunk_size);
1435 if (chunk_size == NULL)
1436 goto fail;
1437 input_chunk = PyObject_CallMethodObjArgs(self->buffer,
1438 _PyIO_str_read1, chunk_size, NULL);
1439 Py_DECREF(chunk_size);
1440 if (input_chunk == NULL)
1441 goto fail;
1442 assert(PyBytes_Check(input_chunk));
1443
Antoine Pitrou211b81d2011-02-25 20:27:33 +00001444 nbytes = PyBytes_Size(input_chunk);
1445 eof = (nbytes == 0);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001446
1447 if (Py_TYPE(self->decoder) == &PyIncrementalNewlineDecoder_Type) {
1448 decoded_chars = _PyIncrementalNewlineDecoder_decode(
1449 self->decoder, input_chunk, eof);
1450 }
1451 else {
1452 decoded_chars = PyObject_CallMethodObjArgs(self->decoder,
1453 _PyIO_str_decode, input_chunk, eof ? Py_True : Py_False, NULL);
1454 }
1455
1456 /* TODO sanity check: isinstance(decoded_chars, unicode) */
1457 if (decoded_chars == NULL)
1458 goto fail;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001459 textiowrapper_set_decoded_chars(self, decoded_chars);
Antoine Pitrou211b81d2011-02-25 20:27:33 +00001460 nchars = PyUnicode_GET_SIZE(decoded_chars);
1461 if (nchars > 0)
1462 self->b2cratio = (double) nbytes / nchars;
1463 else
1464 self->b2cratio = 0.0;
1465 if (nchars > 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001466 eof = 0;
1467
1468 if (self->telling) {
1469 /* At the snapshot point, len(dec_buffer) bytes before the read, the
1470 * next input to be decoded is dec_buffer + input_chunk.
1471 */
1472 PyObject *next_input = PyNumber_Add(dec_buffer, input_chunk);
1473 if (next_input == NULL)
1474 goto fail;
1475 assert (PyBytes_Check(next_input));
1476 Py_DECREF(dec_buffer);
1477 Py_CLEAR(self->snapshot);
1478 self->snapshot = Py_BuildValue("NN", dec_flags, next_input);
1479 }
1480 Py_DECREF(input_chunk);
1481
1482 return (eof == 0);
1483
1484 fail:
1485 Py_XDECREF(dec_buffer);
1486 Py_XDECREF(dec_flags);
1487 Py_XDECREF(input_chunk);
1488 return -1;
1489}
1490
1491static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001492textiowrapper_read(textio *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001493{
1494 Py_ssize_t n = -1;
1495 PyObject *result = NULL, *chunks = NULL;
1496
1497 CHECK_INITIALIZED(self);
1498
Benjamin Petersonbf5ff762009-12-13 19:25:34 +00001499 if (!PyArg_ParseTuple(args, "|O&:read", &_PyIO_ConvertSsize_t, &n))
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001500 return NULL;
1501
1502 CHECK_CLOSED(self);
1503
Antoine Pitrou0d739d72010-09-05 23:01:12 +00001504 if (self->decoder == NULL)
1505 return _unsupported("not readable");
Benjamin Petersona1b49012009-03-31 23:11:32 +00001506
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001507 if (_textiowrapper_writeflush(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001508 return NULL;
1509
1510 if (n < 0) {
1511 /* Read everything */
1512 PyObject *bytes = PyObject_CallMethod(self->buffer, "read", NULL);
1513 PyObject *decoded;
1514 if (bytes == NULL)
1515 goto fail;
Victor Stinnerfd821132011-05-25 22:01:33 +02001516
1517 if (Py_TYPE(self->decoder) == &PyIncrementalNewlineDecoder_Type)
1518 decoded = _PyIncrementalNewlineDecoder_decode(self->decoder,
1519 bytes, 1);
1520 else
1521 decoded = PyObject_CallMethodObjArgs(
1522 self->decoder, _PyIO_str_decode, bytes, Py_True, NULL);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001523 Py_DECREF(bytes);
1524 if (decoded == NULL)
1525 goto fail;
1526
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001527 result = textiowrapper_get_decoded_chars(self, -1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001528
1529 if (result == NULL) {
1530 Py_DECREF(decoded);
1531 return NULL;
1532 }
1533
1534 PyUnicode_AppendAndDel(&result, decoded);
1535 if (result == NULL)
1536 goto fail;
1537
1538 Py_CLEAR(self->snapshot);
1539 return result;
1540 }
1541 else {
1542 int res = 1;
1543 Py_ssize_t remaining = n;
1544
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001545 result = textiowrapper_get_decoded_chars(self, n);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001546 if (result == NULL)
1547 goto fail;
1548 remaining -= PyUnicode_GET_SIZE(result);
1549
1550 /* Keep reading chunks until we have n characters to return */
1551 while (remaining > 0) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001552 res = textiowrapper_read_chunk(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001553 if (res < 0)
1554 goto fail;
1555 if (res == 0) /* EOF */
1556 break;
1557 if (chunks == NULL) {
1558 chunks = PyList_New(0);
1559 if (chunks == NULL)
1560 goto fail;
1561 }
1562 if (PyList_Append(chunks, result) < 0)
1563 goto fail;
1564 Py_DECREF(result);
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001565 result = textiowrapper_get_decoded_chars(self, remaining);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001566 if (result == NULL)
1567 goto fail;
1568 remaining -= PyUnicode_GET_SIZE(result);
1569 }
1570 if (chunks != NULL) {
1571 if (result != NULL && PyList_Append(chunks, result) < 0)
1572 goto fail;
1573 Py_CLEAR(result);
1574 result = PyUnicode_Join(_PyIO_empty_str, chunks);
1575 if (result == NULL)
1576 goto fail;
1577 Py_CLEAR(chunks);
1578 }
1579 return result;
1580 }
1581 fail:
1582 Py_XDECREF(result);
1583 Py_XDECREF(chunks);
1584 return NULL;
1585}
1586
1587
1588/* NOTE: `end` must point to the real end of the Py_UNICODE storage,
1589 that is to the NUL character. Otherwise the function will produce
1590 incorrect results. */
1591static Py_UNICODE *
1592find_control_char(Py_UNICODE *start, Py_UNICODE *end, Py_UNICODE ch)
1593{
1594 Py_UNICODE *s = start;
1595 for (;;) {
1596 while (*s > ch)
1597 s++;
1598 if (*s == ch)
1599 return s;
1600 if (s == end)
1601 return NULL;
1602 s++;
1603 }
1604}
1605
1606Py_ssize_t
1607_PyIO_find_line_ending(
1608 int translated, int universal, PyObject *readnl,
1609 Py_UNICODE *start, Py_UNICODE *end, Py_ssize_t *consumed)
1610{
1611 Py_ssize_t len = end - start;
1612
1613 if (translated) {
1614 /* Newlines are already translated, only search for \n */
1615 Py_UNICODE *pos = find_control_char(start, end, '\n');
1616 if (pos != NULL)
1617 return pos - start + 1;
1618 else {
1619 *consumed = len;
1620 return -1;
1621 }
1622 }
1623 else if (universal) {
1624 /* Universal newline search. Find any of \r, \r\n, \n
1625 * The decoder ensures that \r\n are not split in two pieces
1626 */
1627 Py_UNICODE *s = start;
1628 for (;;) {
1629 Py_UNICODE ch;
1630 /* Fast path for non-control chars. The loop always ends
1631 since the Py_UNICODE storage is NUL-terminated. */
1632 while (*s > '\r')
1633 s++;
1634 if (s >= end) {
1635 *consumed = len;
1636 return -1;
1637 }
1638 ch = *s++;
1639 if (ch == '\n')
1640 return s - start;
1641 if (ch == '\r') {
1642 if (*s == '\n')
1643 return s - start + 1;
1644 else
1645 return s - start;
1646 }
1647 }
1648 }
1649 else {
1650 /* Non-universal mode. */
1651 Py_ssize_t readnl_len = PyUnicode_GET_SIZE(readnl);
1652 Py_UNICODE *nl = PyUnicode_AS_UNICODE(readnl);
1653 if (readnl_len == 1) {
1654 Py_UNICODE *pos = find_control_char(start, end, nl[0]);
1655 if (pos != NULL)
1656 return pos - start + 1;
1657 *consumed = len;
1658 return -1;
1659 }
1660 else {
1661 Py_UNICODE *s = start;
1662 Py_UNICODE *e = end - readnl_len + 1;
1663 Py_UNICODE *pos;
1664 if (e < s)
1665 e = s;
1666 while (s < e) {
1667 Py_ssize_t i;
1668 Py_UNICODE *pos = find_control_char(s, end, nl[0]);
1669 if (pos == NULL || pos >= e)
1670 break;
1671 for (i = 1; i < readnl_len; i++) {
1672 if (pos[i] != nl[i])
1673 break;
1674 }
1675 if (i == readnl_len)
1676 return pos - start + readnl_len;
1677 s = pos + 1;
1678 }
1679 pos = find_control_char(e, end, nl[0]);
1680 if (pos == NULL)
1681 *consumed = len;
1682 else
1683 *consumed = pos - start;
1684 return -1;
1685 }
1686 }
1687}
1688
1689static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001690_textiowrapper_readline(textio *self, Py_ssize_t limit)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001691{
1692 PyObject *line = NULL, *chunks = NULL, *remaining = NULL;
1693 Py_ssize_t start, endpos, chunked, offset_to_buffer;
1694 int res;
1695
1696 CHECK_CLOSED(self);
1697
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001698 if (_textiowrapper_writeflush(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001699 return NULL;
1700
1701 chunked = 0;
1702
1703 while (1) {
1704 Py_UNICODE *ptr;
1705 Py_ssize_t line_len;
1706 Py_ssize_t consumed = 0;
1707
1708 /* First, get some data if necessary */
1709 res = 1;
1710 while (!self->decoded_chars ||
1711 !PyUnicode_GET_SIZE(self->decoded_chars)) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001712 res = textiowrapper_read_chunk(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001713 if (res < 0)
1714 goto error;
1715 if (res == 0)
1716 break;
1717 }
1718 if (res == 0) {
1719 /* end of file */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001720 textiowrapper_set_decoded_chars(self, NULL);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001721 Py_CLEAR(self->snapshot);
1722 start = endpos = offset_to_buffer = 0;
1723 break;
1724 }
1725
1726 if (remaining == NULL) {
1727 line = self->decoded_chars;
1728 start = self->decoded_chars_used;
1729 offset_to_buffer = 0;
1730 Py_INCREF(line);
1731 }
1732 else {
1733 assert(self->decoded_chars_used == 0);
1734 line = PyUnicode_Concat(remaining, self->decoded_chars);
1735 start = 0;
1736 offset_to_buffer = PyUnicode_GET_SIZE(remaining);
1737 Py_CLEAR(remaining);
1738 if (line == NULL)
1739 goto error;
1740 }
1741
1742 ptr = PyUnicode_AS_UNICODE(line);
1743 line_len = PyUnicode_GET_SIZE(line);
1744
1745 endpos = _PyIO_find_line_ending(
1746 self->readtranslate, self->readuniversal, self->readnl,
1747 ptr + start, ptr + line_len, &consumed);
1748 if (endpos >= 0) {
1749 endpos += start;
1750 if (limit >= 0 && (endpos - start) + chunked >= limit)
1751 endpos = start + limit - chunked;
1752 break;
1753 }
1754
1755 /* We can put aside up to `endpos` */
1756 endpos = consumed + start;
1757 if (limit >= 0 && (endpos - start) + chunked >= limit) {
1758 /* Didn't find line ending, but reached length limit */
1759 endpos = start + limit - chunked;
1760 break;
1761 }
1762
1763 if (endpos > start) {
1764 /* No line ending seen yet - put aside current data */
1765 PyObject *s;
1766 if (chunks == NULL) {
1767 chunks = PyList_New(0);
1768 if (chunks == NULL)
1769 goto error;
1770 }
1771 s = PyUnicode_FromUnicode(ptr + start, endpos - start);
1772 if (s == NULL)
1773 goto error;
1774 if (PyList_Append(chunks, s) < 0) {
1775 Py_DECREF(s);
1776 goto error;
1777 }
1778 chunked += PyUnicode_GET_SIZE(s);
1779 Py_DECREF(s);
1780 }
1781 /* There may be some remaining bytes we'll have to prepend to the
1782 next chunk of data */
1783 if (endpos < line_len) {
1784 remaining = PyUnicode_FromUnicode(
1785 ptr + endpos, line_len - endpos);
1786 if (remaining == NULL)
1787 goto error;
1788 }
1789 Py_CLEAR(line);
1790 /* We have consumed the buffer */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001791 textiowrapper_set_decoded_chars(self, NULL);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001792 }
1793
1794 if (line != NULL) {
1795 /* Our line ends in the current buffer */
1796 self->decoded_chars_used = endpos - offset_to_buffer;
1797 if (start > 0 || endpos < PyUnicode_GET_SIZE(line)) {
1798 if (start == 0 && Py_REFCNT(line) == 1) {
1799 if (PyUnicode_Resize(&line, endpos) < 0)
1800 goto error;
1801 }
1802 else {
1803 PyObject *s = PyUnicode_FromUnicode(
1804 PyUnicode_AS_UNICODE(line) + start, endpos - start);
1805 Py_CLEAR(line);
1806 if (s == NULL)
1807 goto error;
1808 line = s;
1809 }
1810 }
1811 }
1812 if (remaining != NULL) {
1813 if (chunks == NULL) {
1814 chunks = PyList_New(0);
1815 if (chunks == NULL)
1816 goto error;
1817 }
1818 if (PyList_Append(chunks, remaining) < 0)
1819 goto error;
1820 Py_CLEAR(remaining);
1821 }
1822 if (chunks != NULL) {
1823 if (line != NULL && PyList_Append(chunks, line) < 0)
1824 goto error;
1825 Py_CLEAR(line);
1826 line = PyUnicode_Join(_PyIO_empty_str, chunks);
1827 if (line == NULL)
1828 goto error;
1829 Py_DECREF(chunks);
1830 }
1831 if (line == NULL)
1832 line = PyUnicode_FromStringAndSize(NULL, 0);
1833
1834 return line;
1835
1836 error:
1837 Py_XDECREF(chunks);
1838 Py_XDECREF(remaining);
1839 Py_XDECREF(line);
1840 return NULL;
1841}
1842
1843static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001844textiowrapper_readline(textio *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001845{
1846 Py_ssize_t limit = -1;
1847
1848 CHECK_INITIALIZED(self);
1849 if (!PyArg_ParseTuple(args, "|n:readline", &limit)) {
1850 return NULL;
1851 }
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001852 return _textiowrapper_readline(self, limit);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001853}
1854
1855/* Seek and Tell */
1856
1857typedef struct {
1858 Py_off_t start_pos;
1859 int dec_flags;
1860 int bytes_to_feed;
1861 int chars_to_skip;
1862 char need_eof;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001863} cookie_type;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001864
1865/*
1866 To speed up cookie packing/unpacking, we store the fields in a temporary
1867 string and call _PyLong_FromByteArray() or _PyLong_AsByteArray (resp.).
1868 The following macros define at which offsets in the intermediary byte
1869 string the various CookieStruct fields will be stored.
1870 */
1871
1872#define COOKIE_BUF_LEN (sizeof(Py_off_t) + 3 * sizeof(int) + sizeof(char))
1873
1874#if defined(WORDS_BIGENDIAN)
1875
1876# define IS_LITTLE_ENDIAN 0
1877
1878/* We want the least significant byte of start_pos to also be the least
1879 significant byte of the cookie, which means that in big-endian mode we
1880 must copy the fields in reverse order. */
1881
1882# define OFF_START_POS (sizeof(char) + 3 * sizeof(int))
1883# define OFF_DEC_FLAGS (sizeof(char) + 2 * sizeof(int))
1884# define OFF_BYTES_TO_FEED (sizeof(char) + sizeof(int))
1885# define OFF_CHARS_TO_SKIP (sizeof(char))
1886# define OFF_NEED_EOF 0
1887
1888#else
1889
1890# define IS_LITTLE_ENDIAN 1
1891
1892/* Little-endian mode: the least significant byte of start_pos will
1893 naturally end up the least significant byte of the cookie. */
1894
1895# define OFF_START_POS 0
1896# define OFF_DEC_FLAGS (sizeof(Py_off_t))
1897# define OFF_BYTES_TO_FEED (sizeof(Py_off_t) + sizeof(int))
1898# define OFF_CHARS_TO_SKIP (sizeof(Py_off_t) + 2 * sizeof(int))
1899# define OFF_NEED_EOF (sizeof(Py_off_t) + 3 * sizeof(int))
1900
1901#endif
1902
1903static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001904textiowrapper_parse_cookie(cookie_type *cookie, PyObject *cookieObj)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001905{
1906 unsigned char buffer[COOKIE_BUF_LEN];
1907 PyLongObject *cookieLong = (PyLongObject *)PyNumber_Long(cookieObj);
1908 if (cookieLong == NULL)
1909 return -1;
1910
1911 if (_PyLong_AsByteArray(cookieLong, buffer, sizeof(buffer),
1912 IS_LITTLE_ENDIAN, 0) < 0) {
1913 Py_DECREF(cookieLong);
1914 return -1;
1915 }
1916 Py_DECREF(cookieLong);
1917
Antoine Pitrou2db74c22009-03-06 21:49:02 +00001918 memcpy(&cookie->start_pos, buffer + OFF_START_POS, sizeof(cookie->start_pos));
1919 memcpy(&cookie->dec_flags, buffer + OFF_DEC_FLAGS, sizeof(cookie->dec_flags));
1920 memcpy(&cookie->bytes_to_feed, buffer + OFF_BYTES_TO_FEED, sizeof(cookie->bytes_to_feed));
1921 memcpy(&cookie->chars_to_skip, buffer + OFF_CHARS_TO_SKIP, sizeof(cookie->chars_to_skip));
1922 memcpy(&cookie->need_eof, buffer + OFF_NEED_EOF, sizeof(cookie->need_eof));
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001923
1924 return 0;
1925}
1926
1927static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001928textiowrapper_build_cookie(cookie_type *cookie)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001929{
1930 unsigned char buffer[COOKIE_BUF_LEN];
1931
Antoine Pitrou2db74c22009-03-06 21:49:02 +00001932 memcpy(buffer + OFF_START_POS, &cookie->start_pos, sizeof(cookie->start_pos));
1933 memcpy(buffer + OFF_DEC_FLAGS, &cookie->dec_flags, sizeof(cookie->dec_flags));
1934 memcpy(buffer + OFF_BYTES_TO_FEED, &cookie->bytes_to_feed, sizeof(cookie->bytes_to_feed));
1935 memcpy(buffer + OFF_CHARS_TO_SKIP, &cookie->chars_to_skip, sizeof(cookie->chars_to_skip));
1936 memcpy(buffer + OFF_NEED_EOF, &cookie->need_eof, sizeof(cookie->need_eof));
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001937
1938 return _PyLong_FromByteArray(buffer, sizeof(buffer), IS_LITTLE_ENDIAN, 0);
1939}
1940#undef IS_LITTLE_ENDIAN
1941
1942static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001943_textiowrapper_decoder_setstate(textio *self, cookie_type *cookie)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001944{
1945 PyObject *res;
1946 /* When seeking to the start of the stream, we call decoder.reset()
1947 rather than decoder.getstate().
1948 This is for a few decoders such as utf-16 for which the state value
1949 at start is not (b"", 0) but e.g. (b"", 2) (meaning, in the case of
1950 utf-16, that we are expecting a BOM).
1951 */
1952 if (cookie->start_pos == 0 && cookie->dec_flags == 0)
1953 res = PyObject_CallMethodObjArgs(self->decoder, _PyIO_str_reset, NULL);
1954 else
1955 res = PyObject_CallMethod(self->decoder, "setstate",
1956 "((yi))", "", cookie->dec_flags);
1957 if (res == NULL)
1958 return -1;
1959 Py_DECREF(res);
1960 return 0;
1961}
1962
Antoine Pitroue4501852009-05-14 18:55:55 +00001963static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001964_textiowrapper_encoder_setstate(textio *self, cookie_type *cookie)
Antoine Pitroue4501852009-05-14 18:55:55 +00001965{
1966 PyObject *res;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001967 /* Same as _textiowrapper_decoder_setstate() above. */
Antoine Pitroue4501852009-05-14 18:55:55 +00001968 if (cookie->start_pos == 0 && cookie->dec_flags == 0) {
1969 res = PyObject_CallMethodObjArgs(self->encoder, _PyIO_str_reset, NULL);
1970 self->encoding_start_of_stream = 1;
1971 }
1972 else {
1973 res = PyObject_CallMethodObjArgs(self->encoder, _PyIO_str_setstate,
1974 _PyIO_zero, NULL);
1975 self->encoding_start_of_stream = 0;
1976 }
1977 if (res == NULL)
1978 return -1;
1979 Py_DECREF(res);
1980 return 0;
1981}
1982
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001983static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001984textiowrapper_seek(textio *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001985{
1986 PyObject *cookieObj, *posobj;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00001987 cookie_type cookie;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001988 int whence = 0;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001989 PyObject *res;
1990 int cmp;
1991
1992 CHECK_INITIALIZED(self);
1993
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00001994 if (!PyArg_ParseTuple(args, "O|i:seek", &cookieObj, &whence))
1995 return NULL;
1996 CHECK_CLOSED(self);
1997
1998 Py_INCREF(cookieObj);
1999
2000 if (!self->seekable) {
Antoine Pitrou0d739d72010-09-05 23:01:12 +00002001 _unsupported("underlying stream is not seekable");
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002002 goto fail;
2003 }
2004
2005 if (whence == 1) {
2006 /* seek relative to current position */
Antoine Pitroue4501852009-05-14 18:55:55 +00002007 cmp = PyObject_RichCompareBool(cookieObj, _PyIO_zero, Py_EQ);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002008 if (cmp < 0)
2009 goto fail;
2010
2011 if (cmp == 0) {
Antoine Pitrou0d739d72010-09-05 23:01:12 +00002012 _unsupported("can't do nonzero cur-relative seeks");
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002013 goto fail;
2014 }
2015
2016 /* Seeking to the current position should attempt to
2017 * sync the underlying buffer with the current position.
2018 */
2019 Py_DECREF(cookieObj);
2020 cookieObj = PyObject_CallMethod((PyObject *)self, "tell", NULL);
2021 if (cookieObj == NULL)
2022 goto fail;
2023 }
2024 else if (whence == 2) {
2025 /* seek relative to end of file */
2026
Antoine Pitroue4501852009-05-14 18:55:55 +00002027 cmp = PyObject_RichCompareBool(cookieObj, _PyIO_zero, Py_EQ);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002028 if (cmp < 0)
2029 goto fail;
2030
2031 if (cmp == 0) {
Antoine Pitrou0d739d72010-09-05 23:01:12 +00002032 _unsupported("can't do nonzero end-relative seeks");
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002033 goto fail;
2034 }
2035
2036 res = PyObject_CallMethod((PyObject *)self, "flush", NULL);
2037 if (res == NULL)
2038 goto fail;
2039 Py_DECREF(res);
2040
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002041 textiowrapper_set_decoded_chars(self, NULL);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002042 Py_CLEAR(self->snapshot);
2043 if (self->decoder) {
2044 res = PyObject_CallMethod(self->decoder, "reset", NULL);
2045 if (res == NULL)
2046 goto fail;
2047 Py_DECREF(res);
2048 }
2049
2050 res = PyObject_CallMethod(self->buffer, "seek", "ii", 0, 2);
2051 Py_XDECREF(cookieObj);
2052 return res;
2053 }
2054 else if (whence != 0) {
2055 PyErr_Format(PyExc_ValueError,
2056 "invalid whence (%d, should be 0, 1 or 2)", whence);
2057 goto fail;
2058 }
2059
Antoine Pitroue4501852009-05-14 18:55:55 +00002060 cmp = PyObject_RichCompareBool(cookieObj, _PyIO_zero, Py_LT);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002061 if (cmp < 0)
2062 goto fail;
2063
2064 if (cmp == 1) {
2065 PyErr_Format(PyExc_ValueError,
2066 "negative seek position %R", cookieObj);
2067 goto fail;
2068 }
2069
2070 res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL);
2071 if (res == NULL)
2072 goto fail;
2073 Py_DECREF(res);
2074
2075 /* The strategy of seek() is to go back to the safe start point
2076 * and replay the effect of read(chars_to_skip) from there.
2077 */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002078 if (textiowrapper_parse_cookie(&cookie, cookieObj) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002079 goto fail;
2080
2081 /* Seek back to the safe start point. */
2082 posobj = PyLong_FromOff_t(cookie.start_pos);
2083 if (posobj == NULL)
2084 goto fail;
2085 res = PyObject_CallMethodObjArgs(self->buffer,
2086 _PyIO_str_seek, posobj, NULL);
2087 Py_DECREF(posobj);
2088 if (res == NULL)
2089 goto fail;
2090 Py_DECREF(res);
2091
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002092 textiowrapper_set_decoded_chars(self, NULL);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002093 Py_CLEAR(self->snapshot);
2094
2095 /* Restore the decoder to its state from the safe start point. */
2096 if (self->decoder) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002097 if (_textiowrapper_decoder_setstate(self, &cookie) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002098 goto fail;
2099 }
2100
2101 if (cookie.chars_to_skip) {
2102 /* Just like _read_chunk, feed the decoder and save a snapshot. */
2103 PyObject *input_chunk = PyObject_CallMethod(
2104 self->buffer, "read", "i", cookie.bytes_to_feed);
2105 PyObject *decoded;
2106
2107 if (input_chunk == NULL)
2108 goto fail;
2109
2110 assert (PyBytes_Check(input_chunk));
2111
2112 self->snapshot = Py_BuildValue("iN", cookie.dec_flags, input_chunk);
2113 if (self->snapshot == NULL) {
2114 Py_DECREF(input_chunk);
2115 goto fail;
2116 }
2117
2118 decoded = PyObject_CallMethod(self->decoder, "decode",
2119 "Oi", input_chunk, (int)cookie.need_eof);
2120
2121 if (decoded == NULL)
2122 goto fail;
2123
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002124 textiowrapper_set_decoded_chars(self, decoded);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002125
2126 /* Skip chars_to_skip of the decoded characters. */
2127 if (PyUnicode_GetSize(self->decoded_chars) < cookie.chars_to_skip) {
2128 PyErr_SetString(PyExc_IOError, "can't restore logical file position");
2129 goto fail;
2130 }
2131 self->decoded_chars_used = cookie.chars_to_skip;
2132 }
2133 else {
2134 self->snapshot = Py_BuildValue("iy", cookie.dec_flags, "");
2135 if (self->snapshot == NULL)
2136 goto fail;
2137 }
2138
Antoine Pitroue4501852009-05-14 18:55:55 +00002139 /* Finally, reset the encoder (merely useful for proper BOM handling) */
2140 if (self->encoder) {
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002141 if (_textiowrapper_encoder_setstate(self, &cookie) < 0)
Antoine Pitroue4501852009-05-14 18:55:55 +00002142 goto fail;
2143 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002144 return cookieObj;
2145 fail:
2146 Py_XDECREF(cookieObj);
2147 return NULL;
2148
2149}
2150
2151static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002152textiowrapper_tell(textio *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002153{
2154 PyObject *res;
2155 PyObject *posobj = NULL;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002156 cookie_type cookie = {0,0,0,0,0};
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002157 PyObject *next_input;
2158 Py_ssize_t chars_to_skip, chars_decoded;
Antoine Pitrou211b81d2011-02-25 20:27:33 +00002159 Py_ssize_t skip_bytes, skip_back;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002160 PyObject *saved_state = NULL;
2161 char *input, *input_end;
Antoine Pitrou211b81d2011-02-25 20:27:33 +00002162 char *dec_buffer;
2163 Py_ssize_t dec_buffer_len;
2164 int dec_flags;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002165
2166 CHECK_INITIALIZED(self);
2167 CHECK_CLOSED(self);
2168
2169 if (!self->seekable) {
Antoine Pitrou0d739d72010-09-05 23:01:12 +00002170 _unsupported("underlying stream is not seekable");
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002171 goto fail;
2172 }
2173 if (!self->telling) {
2174 PyErr_SetString(PyExc_IOError,
2175 "telling position disabled by next() call");
2176 goto fail;
2177 }
2178
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002179 if (_textiowrapper_writeflush(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002180 return NULL;
2181 res = PyObject_CallMethod((PyObject *)self, "flush", NULL);
2182 if (res == NULL)
2183 goto fail;
2184 Py_DECREF(res);
2185
2186 posobj = PyObject_CallMethod(self->buffer, "tell", NULL);
2187 if (posobj == NULL)
2188 goto fail;
2189
2190 if (self->decoder == NULL || self->snapshot == NULL) {
2191 assert (self->decoded_chars == NULL || PyUnicode_GetSize(self->decoded_chars) == 0);
2192 return posobj;
2193 }
2194
2195#if defined(HAVE_LARGEFILE_SUPPORT)
2196 cookie.start_pos = PyLong_AsLongLong(posobj);
2197#else
2198 cookie.start_pos = PyLong_AsLong(posobj);
2199#endif
Antoine Pitrou211b81d2011-02-25 20:27:33 +00002200 Py_DECREF(posobj);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002201 if (PyErr_Occurred())
2202 goto fail;
2203
2204 /* Skip backward to the snapshot point (see _read_chunk). */
2205 if (!PyArg_Parse(self->snapshot, "(iO)", &cookie.dec_flags, &next_input))
2206 goto fail;
2207
2208 assert (PyBytes_Check(next_input));
2209
2210 cookie.start_pos -= PyBytes_GET_SIZE(next_input);
2211
2212 /* How many decoded characters have been used up since the snapshot? */
2213 if (self->decoded_chars_used == 0) {
2214 /* We haven't moved from the snapshot point. */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002215 return textiowrapper_build_cookie(&cookie);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002216 }
2217
2218 chars_to_skip = self->decoded_chars_used;
2219
Antoine Pitrou211b81d2011-02-25 20:27:33 +00002220 /* Decoder state will be restored at the end */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002221 saved_state = PyObject_CallMethodObjArgs(self->decoder,
2222 _PyIO_str_getstate, NULL);
2223 if (saved_state == NULL)
2224 goto fail;
2225
Antoine Pitrou211b81d2011-02-25 20:27:33 +00002226#define DECODER_GETSTATE() do { \
2227 PyObject *_state = PyObject_CallMethodObjArgs(self->decoder, \
2228 _PyIO_str_getstate, NULL); \
2229 if (_state == NULL) \
2230 goto fail; \
2231 if (!PyArg_Parse(_state, "(y#i)", &dec_buffer, &dec_buffer_len, &dec_flags)) { \
2232 Py_DECREF(_state); \
2233 goto fail; \
2234 } \
2235 Py_DECREF(_state); \
2236 } while (0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002237
Antoine Pitrou211b81d2011-02-25 20:27:33 +00002238 /* TODO: replace assert with exception */
2239#define DECODER_DECODE(start, len, res) do { \
2240 PyObject *_decoded = PyObject_CallMethod( \
2241 self->decoder, "decode", "y#", start, len); \
2242 if (_decoded == NULL) \
2243 goto fail; \
2244 assert (PyUnicode_Check(_decoded)); \
2245 res = PyUnicode_GET_SIZE(_decoded); \
2246 Py_DECREF(_decoded); \
2247 } while (0)
2248
2249 /* Fast search for an acceptable start point, close to our
2250 current pos */
2251 skip_bytes = (Py_ssize_t) (self->b2cratio * chars_to_skip);
2252 skip_back = 1;
2253 assert(skip_back <= PyBytes_GET_SIZE(next_input));
2254 input = PyBytes_AS_STRING(next_input);
2255 while (skip_bytes > 0) {
2256 /* Decode up to temptative start point */
2257 if (_textiowrapper_decoder_setstate(self, &cookie) < 0)
2258 goto fail;
2259 DECODER_DECODE(input, skip_bytes, chars_decoded);
2260 if (chars_decoded <= chars_to_skip) {
2261 DECODER_GETSTATE();
2262 if (dec_buffer_len == 0) {
2263 /* Before pos and no bytes buffered in decoder => OK */
2264 cookie.dec_flags = dec_flags;
2265 chars_to_skip -= chars_decoded;
2266 break;
2267 }
2268 /* Skip back by buffered amount and reset heuristic */
2269 skip_bytes -= dec_buffer_len;
2270 skip_back = 1;
2271 }
2272 else {
2273 /* We're too far ahead, skip back a bit */
2274 skip_bytes -= skip_back;
2275 skip_back *= 2;
2276 }
2277 }
2278 if (skip_bytes <= 0) {
2279 skip_bytes = 0;
2280 if (_textiowrapper_decoder_setstate(self, &cookie) < 0)
2281 goto fail;
2282 }
2283
2284 /* Note our initial start point. */
2285 cookie.start_pos += skip_bytes;
2286 cookie.chars_to_skip = chars_to_skip;
2287 if (chars_to_skip == 0)
2288 goto finally;
2289
2290 /* We should be close to the desired position. Now feed the decoder one
2291 * byte at a time until we reach the `chars_to_skip` target.
2292 * As we go, note the nearest "safe start point" before the current
2293 * location (a point where the decoder has nothing buffered, so seek()
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002294 * can safely start from there and advance to this location).
2295 */
2296 chars_decoded = 0;
2297 input = PyBytes_AS_STRING(next_input);
2298 input_end = input + PyBytes_GET_SIZE(next_input);
Antoine Pitrou211b81d2011-02-25 20:27:33 +00002299 input += skip_bytes;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002300 while (input < input_end) {
Antoine Pitrou211b81d2011-02-25 20:27:33 +00002301 Py_ssize_t n;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002302
Antoine Pitrou211b81d2011-02-25 20:27:33 +00002303 DECODER_DECODE(input, 1, n);
2304 /* We got n chars for 1 byte */
2305 chars_decoded += n;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002306 cookie.bytes_to_feed += 1;
Antoine Pitrou211b81d2011-02-25 20:27:33 +00002307 DECODER_GETSTATE();
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002308
2309 if (dec_buffer_len == 0 && chars_decoded <= chars_to_skip) {
2310 /* Decoder buffer is empty, so this is a safe start point. */
2311 cookie.start_pos += cookie.bytes_to_feed;
2312 chars_to_skip -= chars_decoded;
2313 cookie.dec_flags = dec_flags;
2314 cookie.bytes_to_feed = 0;
2315 chars_decoded = 0;
2316 }
2317 if (chars_decoded >= chars_to_skip)
2318 break;
2319 input++;
2320 }
2321 if (input == input_end) {
2322 /* We didn't get enough decoded data; signal EOF to get more. */
2323 PyObject *decoded = PyObject_CallMethod(
2324 self->decoder, "decode", "yi", "", /* final = */ 1);
2325 if (decoded == NULL)
2326 goto fail;
2327 assert (PyUnicode_Check(decoded));
2328 chars_decoded += PyUnicode_GET_SIZE(decoded);
2329 Py_DECREF(decoded);
2330 cookie.need_eof = 1;
2331
2332 if (chars_decoded < chars_to_skip) {
2333 PyErr_SetString(PyExc_IOError,
2334 "can't reconstruct logical file position");
2335 goto fail;
2336 }
2337 }
2338
Antoine Pitrou211b81d2011-02-25 20:27:33 +00002339finally:
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002340 res = PyObject_CallMethod(self->decoder, "setstate", "(O)", saved_state);
2341 Py_DECREF(saved_state);
2342 if (res == NULL)
2343 return NULL;
2344 Py_DECREF(res);
2345
2346 /* The returned cookie corresponds to the last safe start point. */
2347 cookie.chars_to_skip = Py_SAFE_DOWNCAST(chars_to_skip, Py_ssize_t, int);
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002348 return textiowrapper_build_cookie(&cookie);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002349
Antoine Pitrou211b81d2011-02-25 20:27:33 +00002350fail:
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002351 if (saved_state) {
2352 PyObject *type, *value, *traceback;
2353 PyErr_Fetch(&type, &value, &traceback);
2354
2355 res = PyObject_CallMethod(self->decoder, "setstate", "(O)", saved_state);
2356 Py_DECREF(saved_state);
2357 if (res == NULL)
2358 return NULL;
2359 Py_DECREF(res);
2360
2361 PyErr_Restore(type, value, traceback);
2362 }
2363 return NULL;
2364}
2365
2366static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002367textiowrapper_truncate(textio *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002368{
2369 PyObject *pos = Py_None;
2370 PyObject *res;
2371
2372 CHECK_INITIALIZED(self)
2373 if (!PyArg_ParseTuple(args, "|O:truncate", &pos)) {
2374 return NULL;
2375 }
2376
2377 res = PyObject_CallMethodObjArgs((PyObject *) self, _PyIO_str_flush, NULL);
2378 if (res == NULL)
2379 return NULL;
2380 Py_DECREF(res);
2381
Antoine Pitrou905a2ff2010-01-31 22:47:27 +00002382 return PyObject_CallMethodObjArgs(self->buffer, _PyIO_str_truncate, pos, NULL);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002383}
2384
Benjamin Petersonc4c0eae2009-03-09 00:07:03 +00002385static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002386textiowrapper_repr(textio *self)
Benjamin Petersonc4c0eae2009-03-09 00:07:03 +00002387{
Antoine Pitroua4815ca2011-01-09 20:38:15 +00002388 PyObject *nameobj, *modeobj, *res, *s;
Antoine Pitrou716c4442009-05-23 19:04:03 +00002389
2390 CHECK_INITIALIZED(self);
2391
Antoine Pitroua4815ca2011-01-09 20:38:15 +00002392 res = PyUnicode_FromString("<_io.TextIOWrapper");
2393 if (res == NULL)
2394 return NULL;
Antoine Pitrou716c4442009-05-23 19:04:03 +00002395 nameobj = PyObject_GetAttrString((PyObject *) self, "name");
2396 if (nameobj == NULL) {
2397 if (PyErr_ExceptionMatches(PyExc_AttributeError))
2398 PyErr_Clear();
2399 else
Antoine Pitroua4815ca2011-01-09 20:38:15 +00002400 goto error;
Antoine Pitrou716c4442009-05-23 19:04:03 +00002401 }
2402 else {
Antoine Pitroua4815ca2011-01-09 20:38:15 +00002403 s = PyUnicode_FromFormat(" name=%R", nameobj);
Antoine Pitrou716c4442009-05-23 19:04:03 +00002404 Py_DECREF(nameobj);
Antoine Pitroua4815ca2011-01-09 20:38:15 +00002405 if (s == NULL)
2406 goto error;
2407 PyUnicode_AppendAndDel(&res, s);
2408 if (res == NULL)
2409 return NULL;
Antoine Pitrou716c4442009-05-23 19:04:03 +00002410 }
Antoine Pitroua4815ca2011-01-09 20:38:15 +00002411 modeobj = PyObject_GetAttrString((PyObject *) self, "mode");
2412 if (modeobj == NULL) {
2413 if (PyErr_ExceptionMatches(PyExc_AttributeError))
2414 PyErr_Clear();
2415 else
2416 goto error;
2417 }
2418 else {
2419 s = PyUnicode_FromFormat(" mode=%R", modeobj);
2420 Py_DECREF(modeobj);
2421 if (s == NULL)
2422 goto error;
2423 PyUnicode_AppendAndDel(&res, s);
2424 if (res == NULL)
2425 return NULL;
2426 }
2427 s = PyUnicode_FromFormat("%U encoding=%R>",
2428 res, self->encoding);
2429 Py_DECREF(res);
2430 return s;
2431error:
2432 Py_XDECREF(res);
2433 return NULL;
Benjamin Petersonc4c0eae2009-03-09 00:07:03 +00002434}
2435
2436
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002437/* Inquiries */
2438
2439static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002440textiowrapper_fileno(textio *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002441{
2442 CHECK_INITIALIZED(self);
2443 return PyObject_CallMethod(self->buffer, "fileno", NULL);
2444}
2445
2446static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002447textiowrapper_seekable(textio *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002448{
2449 CHECK_INITIALIZED(self);
2450 return PyObject_CallMethod(self->buffer, "seekable", NULL);
2451}
2452
2453static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002454textiowrapper_readable(textio *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002455{
2456 CHECK_INITIALIZED(self);
2457 return PyObject_CallMethod(self->buffer, "readable", NULL);
2458}
2459
2460static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002461textiowrapper_writable(textio *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002462{
2463 CHECK_INITIALIZED(self);
2464 return PyObject_CallMethod(self->buffer, "writable", NULL);
2465}
2466
2467static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002468textiowrapper_isatty(textio *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002469{
2470 CHECK_INITIALIZED(self);
2471 return PyObject_CallMethod(self->buffer, "isatty", NULL);
2472}
2473
2474static PyObject *
Antoine Pitrou243757e2010-11-05 21:15:39 +00002475textiowrapper_getstate(textio *self, PyObject *args)
2476{
2477 PyErr_Format(PyExc_TypeError,
2478 "cannot serialize '%s' object", Py_TYPE(self)->tp_name);
2479 return NULL;
2480}
2481
2482static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002483textiowrapper_flush(textio *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002484{
2485 CHECK_INITIALIZED(self);
2486 CHECK_CLOSED(self);
2487 self->telling = self->seekable;
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002488 if (_textiowrapper_writeflush(self) < 0)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002489 return NULL;
2490 return PyObject_CallMethod(self->buffer, "flush", NULL);
2491}
2492
2493static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002494textiowrapper_close(textio *self, PyObject *args)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002495{
2496 PyObject *res;
Antoine Pitrou6be88762010-05-03 16:48:20 +00002497 int r;
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002498 CHECK_INITIALIZED(self);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002499
Antoine Pitrou6be88762010-05-03 16:48:20 +00002500 res = textiowrapper_closed_get(self, NULL);
2501 if (res == NULL)
2502 return NULL;
2503 r = PyObject_IsTrue(res);
2504 Py_DECREF(res);
2505 if (r < 0)
2506 return NULL;
Victor Stinnerf6c57832010-05-19 01:17:01 +00002507
Antoine Pitrou6be88762010-05-03 16:48:20 +00002508 if (r > 0) {
2509 Py_RETURN_NONE; /* stream already closed */
2510 }
2511 else {
Antoine Pitroue033e062010-10-29 10:38:18 +00002512 if (self->deallocating) {
2513 res = PyObject_CallMethod(self->buffer, "_dealloc_warn", "O", self);
2514 if (res)
2515 Py_DECREF(res);
2516 else
2517 PyErr_Clear();
2518 }
Antoine Pitrou6be88762010-05-03 16:48:20 +00002519 res = PyObject_CallMethod((PyObject *)self, "flush", NULL);
2520 if (res == NULL) {
2521 return NULL;
2522 }
2523 else
2524 Py_DECREF(res);
2525
2526 return PyObject_CallMethod(self->buffer, "close", NULL);
2527 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002528}
2529
2530static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002531textiowrapper_iternext(textio *self)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002532{
2533 PyObject *line;
2534
2535 CHECK_INITIALIZED(self);
2536
2537 self->telling = 0;
2538 if (Py_TYPE(self) == &PyTextIOWrapper_Type) {
2539 /* Skip method call overhead for speed */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002540 line = _textiowrapper_readline(self, -1);
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002541 }
2542 else {
2543 line = PyObject_CallMethodObjArgs((PyObject *)self,
2544 _PyIO_str_readline, NULL);
2545 if (line && !PyUnicode_Check(line)) {
2546 PyErr_Format(PyExc_IOError,
2547 "readline() should have returned an str object, "
2548 "not '%.200s'", Py_TYPE(line)->tp_name);
2549 Py_DECREF(line);
2550 return NULL;
2551 }
2552 }
2553
2554 if (line == NULL)
2555 return NULL;
2556
2557 if (PyUnicode_GET_SIZE(line) == 0) {
2558 /* Reached EOF or would have blocked */
2559 Py_DECREF(line);
2560 Py_CLEAR(self->snapshot);
2561 self->telling = self->seekable;
2562 return NULL;
2563 }
2564
2565 return line;
2566}
2567
2568static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002569textiowrapper_name_get(textio *self, void *context)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002570{
2571 CHECK_INITIALIZED(self);
2572 return PyObject_GetAttrString(self->buffer, "name");
2573}
2574
2575static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002576textiowrapper_closed_get(textio *self, void *context)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002577{
2578 CHECK_INITIALIZED(self);
2579 return PyObject_GetAttr(self->buffer, _PyIO_str_closed);
2580}
2581
2582static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002583textiowrapper_newlines_get(textio *self, void *context)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002584{
2585 PyObject *res;
2586 CHECK_INITIALIZED(self);
2587 if (self->decoder == NULL)
2588 Py_RETURN_NONE;
2589 res = PyObject_GetAttr(self->decoder, _PyIO_str_newlines);
2590 if (res == NULL) {
Benjamin Peterson2cfca792009-06-06 20:46:48 +00002591 if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
2592 PyErr_Clear();
2593 Py_RETURN_NONE;
2594 }
2595 else {
2596 return NULL;
2597 }
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002598 }
2599 return res;
2600}
2601
2602static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002603textiowrapper_errors_get(textio *self, void *context)
Benjamin Peterson0926ad12009-06-06 18:02:12 +00002604{
2605 CHECK_INITIALIZED(self);
2606 return PyUnicode_FromString(PyBytes_AS_STRING(self->errors));
2607}
2608
2609static PyObject *
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002610textiowrapper_chunk_size_get(textio *self, void *context)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002611{
2612 CHECK_INITIALIZED(self);
2613 return PyLong_FromSsize_t(self->chunk_size);
2614}
2615
2616static int
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002617textiowrapper_chunk_size_set(textio *self, PyObject *arg, void *context)
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002618{
2619 Py_ssize_t n;
2620 CHECK_INITIALIZED_INT(self);
2621 n = PyNumber_AsSsize_t(arg, PyExc_TypeError);
2622 if (n == -1 && PyErr_Occurred())
2623 return -1;
2624 if (n <= 0) {
2625 PyErr_SetString(PyExc_ValueError,
2626 "a strictly positive integer is required");
2627 return -1;
2628 }
2629 self->chunk_size = n;
2630 return 0;
2631}
2632
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002633static PyMethodDef textiowrapper_methods[] = {
2634 {"detach", (PyCFunction)textiowrapper_detach, METH_NOARGS},
2635 {"write", (PyCFunction)textiowrapper_write, METH_VARARGS},
2636 {"read", (PyCFunction)textiowrapper_read, METH_VARARGS},
2637 {"readline", (PyCFunction)textiowrapper_readline, METH_VARARGS},
2638 {"flush", (PyCFunction)textiowrapper_flush, METH_NOARGS},
2639 {"close", (PyCFunction)textiowrapper_close, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002640
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002641 {"fileno", (PyCFunction)textiowrapper_fileno, METH_NOARGS},
2642 {"seekable", (PyCFunction)textiowrapper_seekable, METH_NOARGS},
2643 {"readable", (PyCFunction)textiowrapper_readable, METH_NOARGS},
2644 {"writable", (PyCFunction)textiowrapper_writable, METH_NOARGS},
2645 {"isatty", (PyCFunction)textiowrapper_isatty, METH_NOARGS},
Antoine Pitrou243757e2010-11-05 21:15:39 +00002646 {"__getstate__", (PyCFunction)textiowrapper_getstate, METH_NOARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002647
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002648 {"seek", (PyCFunction)textiowrapper_seek, METH_VARARGS},
2649 {"tell", (PyCFunction)textiowrapper_tell, METH_NOARGS},
2650 {"truncate", (PyCFunction)textiowrapper_truncate, METH_VARARGS},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002651 {NULL, NULL}
2652};
2653
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002654static PyMemberDef textiowrapper_members[] = {
2655 {"encoding", T_OBJECT, offsetof(textio, encoding), READONLY},
2656 {"buffer", T_OBJECT, offsetof(textio, buffer), READONLY},
2657 {"line_buffering", T_BOOL, offsetof(textio, line_buffering), READONLY},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002658 {NULL}
2659};
2660
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002661static PyGetSetDef textiowrapper_getset[] = {
2662 {"name", (getter)textiowrapper_name_get, NULL, NULL},
2663 {"closed", (getter)textiowrapper_closed_get, NULL, NULL},
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002664/* {"mode", (getter)TextIOWrapper_mode_get, NULL, NULL},
2665*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002666 {"newlines", (getter)textiowrapper_newlines_get, NULL, NULL},
2667 {"errors", (getter)textiowrapper_errors_get, NULL, NULL},
2668 {"_CHUNK_SIZE", (getter)textiowrapper_chunk_size_get,
2669 (setter)textiowrapper_chunk_size_set, NULL},
Benjamin Peterson1fea3212009-04-19 03:15:20 +00002670 {NULL}
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002671};
2672
2673PyTypeObject PyTextIOWrapper_Type = {
2674 PyVarObject_HEAD_INIT(NULL, 0)
2675 "_io.TextIOWrapper", /*tp_name*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002676 sizeof(textio), /*tp_basicsize*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002677 0, /*tp_itemsize*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002678 (destructor)textiowrapper_dealloc, /*tp_dealloc*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002679 0, /*tp_print*/
2680 0, /*tp_getattr*/
Benjamin Petersonc4c0eae2009-03-09 00:07:03 +00002681 0, /*tps_etattr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002682 0, /*tp_compare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002683 (reprfunc)textiowrapper_repr,/*tp_repr*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002684 0, /*tp_as_number*/
2685 0, /*tp_as_sequence*/
2686 0, /*tp_as_mapping*/
2687 0, /*tp_hash */
2688 0, /*tp_call*/
2689 0, /*tp_str*/
2690 0, /*tp_getattro*/
2691 0, /*tp_setattro*/
2692 0, /*tp_as_buffer*/
2693 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
2694 | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002695 textiowrapper_doc, /* tp_doc */
2696 (traverseproc)textiowrapper_traverse, /* tp_traverse */
2697 (inquiry)textiowrapper_clear, /* tp_clear */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002698 0, /* tp_richcompare */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002699 offsetof(textio, weakreflist), /*tp_weaklistoffset*/
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002700 0, /* tp_iter */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002701 (iternextfunc)textiowrapper_iternext, /* tp_iternext */
2702 textiowrapper_methods, /* tp_methods */
2703 textiowrapper_members, /* tp_members */
2704 textiowrapper_getset, /* tp_getset */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002705 0, /* tp_base */
2706 0, /* tp_dict */
2707 0, /* tp_descr_get */
2708 0, /* tp_descr_set */
Benjamin Peterson680bf1a2009-06-12 02:07:12 +00002709 offsetof(textio, dict), /*tp_dictoffset*/
2710 (initproc)textiowrapper_init, /* tp_init */
Benjamin Peterson4fa88fa2009-03-04 00:14:51 +00002711 0, /* tp_alloc */
2712 PyType_GenericNew, /* tp_new */
2713};