mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
lib/std: fix ByteWriter.read_from method (#793)
* lib/std: fix ByteWriter.read_from method When reading from a stream which does not have an available method, ByteWriter would not make any progress if its buffer was empty. Signed-off-by: Pierre Curto <pierre.curto@gmail.com> * test/unit/stdlib/io: use separate module for TestReader Signed-off-by: Pierre Curto <pierre.curto@gmail.com> --------- Signed-off-by: Pierre Curto <pierre.curto@gmail.com>
This commit is contained in:
@@ -79,19 +79,21 @@ fn void! ByteWriter.write_byte(ByteWriter* writer, char c)
|
|||||||
**/
|
**/
|
||||||
fn usz! ByteWriter.read_from(ByteWriter* writer, Stream* reader)
|
fn usz! ByteWriter.read_from(ByteWriter* writer, Stream* reader)
|
||||||
{
|
{
|
||||||
|
usz start_index = writer.index;
|
||||||
if (reader.supports_available())
|
if (reader.supports_available())
|
||||||
{
|
{
|
||||||
usz total_read = 0;
|
|
||||||
while (usz available = reader.available()!)
|
while (usz available = reader.available()!)
|
||||||
{
|
{
|
||||||
writer.ensure_capacity(writer.index + available)!;
|
writer.ensure_capacity(writer.index + available)!;
|
||||||
usz len = reader.read(writer.bytes[writer.index..])!;
|
usz read = reader.read(writer.bytes[writer.index..])!;
|
||||||
total_read += len;
|
writer.index += read;
|
||||||
writer.index += len;
|
|
||||||
}
|
}
|
||||||
return total_read;
|
return writer.index - start_index;
|
||||||
|
}
|
||||||
|
if (writer.bytes.len == 0)
|
||||||
|
{
|
||||||
|
writer.ensure_capacity(16)!;
|
||||||
}
|
}
|
||||||
usz total_read = 0;
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
// See how much we can read.
|
// See how much we can read.
|
||||||
@@ -100,12 +102,13 @@ fn usz! ByteWriter.read_from(ByteWriter* writer, Stream* reader)
|
|||||||
if (len_to_read < 16)
|
if (len_to_read < 16)
|
||||||
{
|
{
|
||||||
writer.ensure_capacity(writer.bytes.len * 2)!;
|
writer.ensure_capacity(writer.bytes.len * 2)!;
|
||||||
|
len_to_read = writer.bytes.len - writer.index;
|
||||||
}
|
}
|
||||||
// Read into the rest of the buffer
|
// Read into the rest of the buffer
|
||||||
usz read = reader.read(writer.bytes[writer.index..])!;
|
usz read = reader.read(writer.bytes[writer.index..])!;
|
||||||
writer.index += read;
|
writer.index += read;
|
||||||
// Ok, we reached the end.
|
// Ok, we reached the end.
|
||||||
if (read < len_to_read) return total_read;
|
if (read < len_to_read) return writer.index - start_index;
|
||||||
// Otherwise go another round
|
// Otherwise go another round
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -116,4 +119,4 @@ StreamInterface bytewriter_interface = {
|
|||||||
.write_fn = fn (s, char[] bytes) => ((ByteWriter*)s.data).write(bytes),
|
.write_fn = fn (s, char[] bytes) => ((ByteWriter*)s.data).write(bytes),
|
||||||
.write_byte_fn = fn (s, char c) => ((ByteWriter*)s.data).write_byte(c),
|
.write_byte_fn = fn (s, char c) => ((ByteWriter*)s.data).write_byte(c),
|
||||||
.read_stream_fn = fn (s, reader) => ((ByteWriter*)s.data).read_from(reader),
|
.read_stream_fn = fn (s, reader) => ((ByteWriter*)s.data).read_from(reader),
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -35,3 +35,44 @@ fn void! bytewriter_buffer()
|
|||||||
assert(o == "hello");
|
assert(o == "hello");
|
||||||
assert(@catchof(s.write("xxxx")));
|
assert(@catchof(s.write("xxxx")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn void! bytewriter_read_from()
|
||||||
|
{
|
||||||
|
char[] data = "Lorem ipsum dolor sit amet biam.";
|
||||||
|
TestReader r = { .bytes = data };
|
||||||
|
Stream s = r.as_stream();
|
||||||
|
|
||||||
|
ByteWriter bw;
|
||||||
|
bw.tinit();
|
||||||
|
bw.read_from(&s)!;
|
||||||
|
|
||||||
|
assert(bw.as_str() == data);
|
||||||
|
}
|
||||||
|
|
||||||
|
module std::io;
|
||||||
|
// TestReader only has the read method to trigger the path
|
||||||
|
// in ByteWriter.read_from that does not rely on the available method.
|
||||||
|
struct TestReader
|
||||||
|
{
|
||||||
|
char[] bytes;
|
||||||
|
usz index;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn Stream TestReader.as_stream(TestReader *r)
|
||||||
|
{
|
||||||
|
return { .fns = &testReader_interface, .data = r };
|
||||||
|
}
|
||||||
|
|
||||||
|
fn usz! TestReader.read(TestReader *r, char[] bytes)
|
||||||
|
{
|
||||||
|
usz left = r.bytes.len - r.index;
|
||||||
|
if (left == 0) return 0;
|
||||||
|
usz n = min(left, bytes.len);
|
||||||
|
mem::copy(bytes.ptr, &r.bytes[r.index], n);
|
||||||
|
r.index += n;
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
StreamInterface testReader_interface = {
|
||||||
|
.read_fn = fn(s, char[] bytes) => ((TestReader*)s.data).read(bytes),
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user