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