|
|
|
@ -257,6 +257,25 @@ incrementalnewlinedecoder_dealloc(nldecoder_object *self) |
|
|
|
Py_TYPE(self)->tp_free((PyObject *)self); |
|
|
|
} |
|
|
|
|
|
|
|
static int |
|
|
|
check_decoded(PyObject *decoded) |
|
|
|
{ |
|
|
|
if (decoded == NULL) |
|
|
|
return -1; |
|
|
|
if (!PyUnicode_Check(decoded)) { |
|
|
|
PyErr_Format(PyExc_TypeError, |
|
|
|
"decoder should return a string result, not '%.200s'", |
|
|
|
Py_TYPE(decoded)->tp_name); |
|
|
|
Py_DECREF(decoded); |
|
|
|
return -1; |
|
|
|
} |
|
|
|
if (PyUnicode_READY(decoded) < 0) { |
|
|
|
Py_DECREF(decoded); |
|
|
|
return -1; |
|
|
|
} |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
#define SEEN_CR 1 |
|
|
|
#define SEEN_LF 2 |
|
|
|
#define SEEN_CRLF 4 |
|
|
|
@ -286,18 +305,9 @@ _PyIncrementalNewlineDecoder_decode(PyObject *_self, |
|
|
|
Py_INCREF(output); |
|
|
|
} |
|
|
|
|
|
|
|
if (output == NULL) |
|
|
|
if (check_decoded(output) < 0) |
|
|
|
return NULL; |
|
|
|
|
|
|
|
if (!PyUnicode_Check(output)) { |
|
|
|
PyErr_SetString(PyExc_TypeError, |
|
|
|
"decoder should return a string result"); |
|
|
|
goto error; |
|
|
|
} |
|
|
|
|
|
|
|
if (PyUnicode_READY(output) == -1) |
|
|
|
goto error; |
|
|
|
|
|
|
|
output_len = PyUnicode_GET_LENGTH(output); |
|
|
|
if (self->pendingcr && (final || output_len > 0)) { |
|
|
|
/* Prefix output with CR */ |
|
|
|
@ -1458,7 +1468,13 @@ textiowrapper_read_chunk(textio *self, Py_ssize_t size_hint) |
|
|
|
Py_DECREF(chunk_size); |
|
|
|
if (input_chunk == NULL) |
|
|
|
goto fail; |
|
|
|
assert(PyBytes_Check(input_chunk)); |
|
|
|
if (!PyBytes_Check(input_chunk)) { |
|
|
|
PyErr_Format(PyExc_TypeError, |
|
|
|
"underlying %s() should have returned a bytes object, " |
|
|
|
"not '%.200s'", (self->has_read1 ? "read1": "read"), |
|
|
|
Py_TYPE(input_chunk)->tp_name); |
|
|
|
goto fail; |
|
|
|
} |
|
|
|
|
|
|
|
nbytes = PyBytes_Size(input_chunk); |
|
|
|
eof = (nbytes == 0); |
|
|
|
@ -1472,10 +1488,7 @@ textiowrapper_read_chunk(textio *self, Py_ssize_t size_hint) |
|
|
|
_PyIO_str_decode, input_chunk, eof ? Py_True : Py_False, NULL); |
|
|
|
} |
|
|
|
|
|
|
|
/* TODO sanity check: isinstance(decoded_chars, unicode) */ |
|
|
|
if (decoded_chars == NULL) |
|
|
|
goto fail; |
|
|
|
if (PyUnicode_READY(decoded_chars) == -1) |
|
|
|
if (check_decoded(decoded_chars) < 0) |
|
|
|
goto fail; |
|
|
|
textiowrapper_set_decoded_chars(self, decoded_chars); |
|
|
|
nchars = PyUnicode_GET_LENGTH(decoded_chars); |
|
|
|
@ -1493,7 +1506,14 @@ textiowrapper_read_chunk(textio *self, Py_ssize_t size_hint) |
|
|
|
PyObject *next_input = PyNumber_Add(dec_buffer, input_chunk); |
|
|
|
if (next_input == NULL) |
|
|
|
goto fail; |
|
|
|
assert (PyBytes_Check(next_input)); |
|
|
|
if (!PyBytes_Check(next_input)) { |
|
|
|
PyErr_Format(PyExc_TypeError, |
|
|
|
"decoder getstate() should have returned a bytes " |
|
|
|
"object, not '%.200s'", |
|
|
|
Py_TYPE(next_input)->tp_name); |
|
|
|
Py_DECREF(next_input); |
|
|
|
goto fail; |
|
|
|
} |
|
|
|
Py_DECREF(dec_buffer); |
|
|
|
Py_CLEAR(self->snapshot); |
|
|
|
self->snapshot = Py_BuildValue("NN", dec_flags, next_input); |
|
|
|
@ -1542,7 +1562,7 @@ textiowrapper_read(textio *self, PyObject *args) |
|
|
|
decoded = PyObject_CallMethodObjArgs( |
|
|
|
self->decoder, _PyIO_str_decode, bytes, Py_True, NULL); |
|
|
|
Py_DECREF(bytes); |
|
|
|
if (decoded == NULL) |
|
|
|
if (check_decoded(decoded) < 0) |
|
|
|
goto fail; |
|
|
|
|
|
|
|
result = textiowrapper_get_decoded_chars(self, -1); |
|
|
|
@ -2151,7 +2171,14 @@ textiowrapper_seek(textio *self, PyObject *args) |
|
|
|
if (input_chunk == NULL) |
|
|
|
goto fail; |
|
|
|
|
|
|
|
assert (PyBytes_Check(input_chunk)); |
|
|
|
if (!PyBytes_Check(input_chunk)) { |
|
|
|
PyErr_Format(PyExc_TypeError, |
|
|
|
"underlying read() should have returned a bytes " |
|
|
|
"object, not '%.200s'", |
|
|
|
Py_TYPE(input_chunk)->tp_name); |
|
|
|
Py_DECREF(input_chunk); |
|
|
|
goto fail; |
|
|
|
} |
|
|
|
|
|
|
|
self->snapshot = Py_BuildValue("iN", cookie.dec_flags, input_chunk); |
|
|
|
if (self->snapshot == NULL) { |
|
|
|
@ -2162,12 +2189,8 @@ textiowrapper_seek(textio *self, PyObject *args) |
|
|
|
decoded = _PyObject_CallMethodId(self->decoder, &PyId_decode, |
|
|
|
"Oi", input_chunk, (int)cookie.need_eof); |
|
|
|
|
|
|
|
if (decoded == NULL) |
|
|
|
if (check_decoded(decoded) < 0) |
|
|
|
goto fail; |
|
|
|
if (PyUnicode_READY(decoded) == -1) { |
|
|
|
Py_DECREF(decoded); |
|
|
|
goto fail; |
|
|
|
} |
|
|
|
|
|
|
|
textiowrapper_set_decoded_chars(self, decoded); |
|
|
|
|
|
|
|
@ -2283,13 +2306,11 @@ textiowrapper_tell(textio *self, PyObject *args) |
|
|
|
Py_DECREF(_state); \ |
|
|
|
} while (0) |
|
|
|
|
|
|
|
/* TODO: replace assert with exception */ |
|
|
|
#define DECODER_DECODE(start, len, res) do { \ |
|
|
|
PyObject *_decoded = _PyObject_CallMethodId( \ |
|
|
|
self->decoder, &PyId_decode, "y#", start, len); \ |
|
|
|
if (_decoded == NULL) \ |
|
|
|
if (check_decoded(_decoded) < 0) \ |
|
|
|
goto fail; \ |
|
|
|
assert (PyUnicode_Check(_decoded)); \ |
|
|
|
res = PyUnicode_GET_LENGTH(_decoded); \ |
|
|
|
Py_DECREF(_decoded); \ |
|
|
|
} while (0) |
|
|
|
@ -2370,9 +2391,8 @@ textiowrapper_tell(textio *self, PyObject *args) |
|
|
|
/* We didn't get enough decoded data; signal EOF to get more. */ |
|
|
|
PyObject *decoded = _PyObject_CallMethodId( |
|
|
|
self->decoder, &PyId_decode, "yi", "", /* final = */ 1); |
|
|
|
if (decoded == NULL) |
|
|
|
if (check_decoded(decoded) < 0) |
|
|
|
goto fail; |
|
|
|
assert (PyUnicode_Check(decoded)); |
|
|
|
chars_decoded += PyUnicode_GET_LENGTH(decoded); |
|
|
|
Py_DECREF(decoded); |
|
|
|
cookie.need_eof = 1; |
|
|
|
|