From aa62864118b755f10b30fd58a3b7fd8407ce8c6c Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Tue, 13 Mar 2012 01:11:02 -0700 Subject: * stream.c (string_out_byte_flush): Bugfix. Do not loop inside this function. This must not flush out more than one character out of this small buffer, except when we are flushing out the last data. The correct operation is predicated on the assumption that a complete character can be pulled out. That's why we move the buffer to the front after consuming it, and do not automatically flush until there are four bytes. (string_out_put_string): We loop the call to string_out_byte_flush here because when a request comes in to write a Unicode character, we flush all the bytes, even if the tail of those bytes forms an incomplete sequence that turns into U+DCxx codes. (get_string_from_stream): Use the same loop termination test as in string_out_put_string, for consistency. In that function it is needed to prevent infinite looping in the case when the string_out_put_string is being called from string_out_byte_flush and is thus re-entering it. * tests/010/strstream.expected: New file. * tests/010/strstream.txr: New file. --- ChangeLog | 23 +++++++++++++++++++++++ stream.c | 8 ++++---- tests/010/strstream.expected | 1 + tests/010/strstream.txr | 11 +++++++++++ 4 files changed, 39 insertions(+), 4 deletions(-) create mode 100644 tests/010/strstream.expected create mode 100644 tests/010/strstream.txr diff --git a/ChangeLog b/ChangeLog index 17929da5..8298ec3e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,26 @@ +2012-03-13 Kaz Kylheku + + * stream.c (string_out_byte_flush): Bugfix. Do not loop inside this + function. This must not flush out more than one character out of this + small buffer, except when we are flushing out the last data. + The correct operation is predicated on the assumption that + a complete character can be pulled out. That's why we move the + buffer to the front after consuming it, and do not automatically + flush until there are four bytes. + (string_out_put_string): We loop the call to string_out_byte_flush + here because when a request comes in to write a Unicode character, + we flush all the bytes, even if the tail of those bytes forms + an incomplete sequence that turns into U+DCxx codes. + (get_string_from_stream): Use the same loop termination test + as in string_out_put_string, for consistency. In that function + it is needed to prevent infinite looping in the case when + the string_out_put_string is being called from string_out_byte_flush + and is thus re-entering it. + + * tests/010/strstream.expected: New file. + + * tests/010/strstream.txr: New file. + 2012-03-12 Kaz Kylheku Implementing put_byte for string output stream. diff --git a/stream.c b/stream.c index 233ee3d4..e4e75982 100644 --- a/stream.c +++ b/stream.c @@ -468,7 +468,7 @@ static val string_out_byte_flush(struct string_output *so, val stream) { val result = nil; - while (so->tail < so->head) { + if (so->tail < so->head) { wint_t ch = utf8_decode(&so->ud, string_out_byte_callback, (mem_t *) so); int remaining = so->head - so->tail; if (remaining != 0) @@ -480,7 +480,7 @@ static val string_out_byte_flush(struct string_output *so, val stream) result = string_out_put_char(stream, chr(ch)); so->tail = 0; } - return nil; + return result; } static val string_out_put_string(val stream, val str) @@ -490,7 +490,7 @@ static val string_out_put_string(val stream, val str) if (so == 0) return nil; - if (so->head != 0) + while (so->head != so->tail) string_out_byte_flush(so, stream); { @@ -754,7 +754,7 @@ val get_string_from_stream(val stream) if (!so) return out; - if (so->head != 0) + while (so->head != so->tail) out = string_out_byte_flush(so, stream); stream->co.handle = 0; diff --git a/tests/010/strstream.expected b/tests/010/strstream.expected new file mode 100644 index 00000000..7e9cc628 --- /dev/null +++ b/tests/010/strstream.expected @@ -0,0 +1 @@ +"春が来た (Haru-ga Kita/Spring has Come)" diff --git a/tests/010/strstream.txr b/tests/010/strstream.txr new file mode 100644 index 00000000..5800172e --- /dev/null +++ b/tests/010/strstream.txr @@ -0,0 +1,11 @@ +@(do + (defun lazy-byte-stream (s) + (let (ch) (gen (set ch (get-byte s)) ch))) + + (let* ((data "春が来た (Haru-ga Kita/Spring has Come)") + (in-byte (make-string-byte-input-stream data)) + (out-byte (make-string-output-stream))) + (each ((b (lazy-byte-stream in-byte))) + (put-byte b out-byte)) + (print (get-string-from-stream out-byte)) + (pprint "\n"))) -- cgit v1.2.3