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)
|
||||
{
|
||||
usz start_index = writer.index;
|
||||
if (reader.supports_available())
|
||||
{
|
||||
usz total_read = 0;
|
||||
while (usz available = reader.available()!)
|
||||
{
|
||||
writer.ensure_capacity(writer.index + available)!;
|
||||
usz len = reader.read(writer.bytes[writer.index..])!;
|
||||
total_read += len;
|
||||
writer.index += len;
|
||||
usz read = reader.read(writer.bytes[writer.index..])!;
|
||||
writer.index += read;
|
||||
}
|
||||
return total_read;
|
||||
return writer.index - start_index;
|
||||
}
|
||||
if (writer.bytes.len == 0)
|
||||
{
|
||||
writer.ensure_capacity(16)!;
|
||||
}
|
||||
usz total_read = 0;
|
||||
while (true)
|
||||
{
|
||||
// See how much we can read.
|
||||
@@ -100,12 +102,13 @@ fn usz! ByteWriter.read_from(ByteWriter* writer, Stream* reader)
|
||||
if (len_to_read < 16)
|
||||
{
|
||||
writer.ensure_capacity(writer.bytes.len * 2)!;
|
||||
len_to_read = writer.bytes.len - writer.index;
|
||||
}
|
||||
// Read into the rest of the buffer
|
||||
usz read = reader.read(writer.bytes[writer.index..])!;
|
||||
writer.index += read;
|
||||
// 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
|
||||
}
|
||||
}
|
||||
@@ -116,4 +119,4 @@ StreamInterface bytewriter_interface = {
|
||||
.write_fn = fn (s, char[] bytes) => ((ByteWriter*)s.data).write(bytes),
|
||||
.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),
|
||||
};
|
||||
};
|
||||
|
||||
@@ -35,3 +35,44 @@ fn void! bytewriter_buffer()
|
||||
assert(o == "hello");
|
||||
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