mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
io::read_fully now handles unbounded streams properly
This commit is contained in:
@@ -1,7 +1,5 @@
|
||||
module std::io;
|
||||
import std::math;
|
||||
import std::core::env;
|
||||
|
||||
|
||||
interface InStream
|
||||
{
|
||||
@@ -36,7 +34,7 @@ fn usz? available(InStream s)
|
||||
s.seek(curr, Seek.SET)!;
|
||||
return len - curr;
|
||||
}
|
||||
return 0;
|
||||
return ^io::UNSUPPORTED_OPERATION;
|
||||
}
|
||||
|
||||
macro bool @is_instream(#expr) @const
|
||||
@@ -90,21 +88,31 @@ macro usz? read_all(stream, char[] buffer)
|
||||
}
|
||||
|
||||
<*
|
||||
This function will read to the end of the stream.
|
||||
|
||||
@require @is_instream(stream)
|
||||
*>
|
||||
macro char[]? read_fully(Allocator allocator, stream)
|
||||
{
|
||||
usz len = available(stream)!;
|
||||
char* data = allocator::malloc_try(allocator, len)!;
|
||||
defer catch allocator::free(allocator, data);
|
||||
usz read = 0;
|
||||
while (read < len)
|
||||
// Efficient path if it is possible to pre-allocate
|
||||
if (try len = available(stream))
|
||||
{
|
||||
read += stream.read(data[read:len - read])!;
|
||||
char* data = allocator::malloc_try(allocator, len)!;
|
||||
defer catch allocator::free(allocator, data);
|
||||
usz read = 0;
|
||||
while (read < len)
|
||||
{
|
||||
read += stream.read(data[read:len - read])!;
|
||||
}
|
||||
return data[:len];
|
||||
}
|
||||
return data[:len];
|
||||
ByteWriter writer;
|
||||
writer.init(allocator);
|
||||
copy_to(stream, &writer)!;
|
||||
return writer.array_view();
|
||||
}
|
||||
|
||||
|
||||
<*
|
||||
@require @is_outstream(stream)
|
||||
*>
|
||||
|
||||
@@ -43,6 +43,11 @@ fn void? ByteWriter.destroy(&self) @dynamic
|
||||
*self = { };
|
||||
}
|
||||
|
||||
fn char[] ByteWriter.array_view(self) @inline
|
||||
{
|
||||
return self.bytes[:self.index];
|
||||
}
|
||||
|
||||
fn String ByteWriter.str_view(&self) @inline
|
||||
{
|
||||
return (String)self.bytes[:self.index];
|
||||
@@ -91,7 +96,7 @@ fn usz? ByteWriter.read_from(&self, InStream reader) @dynamic
|
||||
}
|
||||
if (self.bytes.len == 0)
|
||||
{
|
||||
self.ensure_capacity(16)!;
|
||||
self.ensure_capacity(256)!;
|
||||
}
|
||||
while (true)
|
||||
{
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
- `String.replace` no longer depends on `String.split`.
|
||||
- Fix the case where `\u<unicode char>` could crash the compiler on some platforms.
|
||||
- Designated initialization with ranges would not error on overflow by 1.
|
||||
- `io::read_fully` now handles unbounded streams properly.
|
||||
|
||||
### Stdlib changes
|
||||
- Add `ThreadPool` join function to wait for all threads to finish in the pool without destroying the threads.
|
||||
|
||||
30
test/unit/stdlib/io/read_full.c3
Normal file
30
test/unit/stdlib/io/read_full.c3
Normal file
@@ -0,0 +1,30 @@
|
||||
module std::io @test;
|
||||
|
||||
struct Test (InStream)
|
||||
{
|
||||
char[] data;
|
||||
int index;
|
||||
}
|
||||
|
||||
fn char? Test.read_byte(&self) @dynamic
|
||||
{
|
||||
if (self.index >= self.data.len) return io::EOF~;
|
||||
return self.data[self.index++];
|
||||
}
|
||||
|
||||
fn usz? Test.read(&self, char[] buffer) @dynamic
|
||||
{
|
||||
io::printn(*self);
|
||||
if (self.index >= self.data.len) return io::EOF~;
|
||||
int len = min((int)self.data.len - self.index, 16);
|
||||
buffer[:len] = self.data[self.index:len];
|
||||
self.index += len;
|
||||
return len;
|
||||
}
|
||||
|
||||
fn void read_fully_stream()
|
||||
{
|
||||
Test t = { .data = "Heokep o opewkfpewkfpoew kfopwekfop ewkf ewopfkewop fopkewfopk ewopfkewpo fkopew kfpoewk fej!" };
|
||||
char[] data = io::read_fully(tmem, &t)!!;
|
||||
test::eq(data, t.data);
|
||||
}
|
||||
Reference in New Issue
Block a user