mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
lib/std/io: add Stream.read_all (#843)
* lib/std/io: add Stream.read_all Signed-off-by: Pierre Curto <pierre.curto@gmail.com> * lib/std/core: use shortened receiver notation Signed-off-by: Pierre Curto <pierre.curto@gmail.com> --------- Signed-off-by: Pierre Curto <pierre.curto@gmail.com>
This commit is contained in:
@@ -62,64 +62,64 @@ fault AllocationFailure
|
||||
|
||||
|
||||
|
||||
macro void*! Allocator.alloc(Allocator* allocator, usz size)
|
||||
macro void*! Allocator.alloc(&allocator, usz size)
|
||||
{
|
||||
return allocator.function(allocator, size, 0, 0, null, ALLOC);
|
||||
return allocator.function(&allocator, size, 0, 0, null, ALLOC);
|
||||
}
|
||||
|
||||
/**
|
||||
* @require alignment && math::is_power_of_2(alignment)
|
||||
*/
|
||||
macro void*! Allocator.alloc_aligned(Allocator* allocator, usz size, usz alignment, usz offset = 0)
|
||||
macro void*! Allocator.alloc_aligned(&allocator, usz size, usz alignment, usz offset = 0)
|
||||
{
|
||||
return allocator.function(allocator, size, alignment, offset, null, ALIGNED_ALLOC);
|
||||
return allocator.function(&allocator, size, alignment, offset, null, ALIGNED_ALLOC);
|
||||
}
|
||||
|
||||
macro void*! Allocator.realloc(Allocator* allocator, void* old_pointer, usz size)
|
||||
macro void*! Allocator.realloc(&allocator, void* old_pointer, usz size)
|
||||
{
|
||||
return allocator.function(allocator, size, 0, 0, old_pointer, REALLOC);
|
||||
return allocator.function(&allocator, size, 0, 0, old_pointer, REALLOC);
|
||||
}
|
||||
|
||||
/**
|
||||
* @require alignment && math::is_power_of_2(alignment)
|
||||
*/
|
||||
macro void*! Allocator.realloc_aligned(Allocator* allocator, void* old_pointer, usz size, usz alignment, usz offset = 0)
|
||||
macro void*! Allocator.realloc_aligned(&allocator, void* old_pointer, usz size, usz alignment, usz offset = 0)
|
||||
{
|
||||
return allocator.function(allocator, size, alignment, offset, old_pointer, ALIGNED_REALLOC);
|
||||
return allocator.function(&allocator, size, alignment, offset, old_pointer, ALIGNED_REALLOC);
|
||||
}
|
||||
|
||||
macro usz Allocator.mark(Allocator* allocator)
|
||||
macro usz Allocator.mark(&allocator)
|
||||
{
|
||||
return (usz)(uptr)allocator.function(allocator, 0, 0, 0, null, MARK) ?? 0;
|
||||
return (usz)(uptr)allocator.function(&allocator, 0, 0, 0, null, MARK) ?? 0;
|
||||
}
|
||||
|
||||
|
||||
macro void*! Allocator.calloc(Allocator* allocator, usz size)
|
||||
macro void*! Allocator.calloc(&allocator, usz size)
|
||||
{
|
||||
return allocator.function(allocator, size, 0, 0, null, CALLOC);
|
||||
return allocator.function(&allocator, size, 0, 0, null, CALLOC);
|
||||
}
|
||||
|
||||
/**
|
||||
* @require alignment && math::is_power_of_2(alignment)
|
||||
*/
|
||||
macro void*! Allocator.calloc_aligned(Allocator* allocator, usz size, usz alignment, usz offset = 0)
|
||||
macro void*! Allocator.calloc_aligned(&allocator, usz size, usz alignment, usz offset = 0)
|
||||
{
|
||||
return allocator.function(allocator, size, alignment, offset, null, ALIGNED_CALLOC);
|
||||
return allocator.function(&allocator, size, alignment, offset, null, ALIGNED_CALLOC);
|
||||
}
|
||||
|
||||
macro void! Allocator.free(Allocator* allocator, void* old_pointer)
|
||||
macro void! Allocator.free(&allocator, void* old_pointer)
|
||||
{
|
||||
allocator.function(allocator, 0, 0, 0, old_pointer, FREE)!;
|
||||
allocator.function(&allocator, 0, 0, 0, old_pointer, FREE)!;
|
||||
}
|
||||
|
||||
macro void! Allocator.free_aligned(Allocator* allocator, void* old_pointer)
|
||||
macro void! Allocator.free_aligned(&allocator, void* old_pointer)
|
||||
{
|
||||
allocator.function(allocator, 0, 0, 0, old_pointer, ALIGNED_FREE)!;
|
||||
allocator.function(&allocator, 0, 0, 0, old_pointer, ALIGNED_FREE)!;
|
||||
}
|
||||
|
||||
macro void Allocator.reset(Allocator* allocator, usz mark = 0)
|
||||
macro void Allocator.reset(&allocator, usz mark = 0)
|
||||
{
|
||||
(void)allocator.function(allocator, mark, 0, 0, null, RESET);
|
||||
(void)allocator.function(&allocator, mark, 0, 0, null, RESET);
|
||||
}
|
||||
|
||||
fn usz alignment_for_allocation(usz alignment) @inline @private
|
||||
|
||||
@@ -85,7 +85,7 @@ fn String join(String[] s, String joiner, Allocator* using = mem::heap())
|
||||
* @param [in] string
|
||||
* @param [in] to_trim
|
||||
**/
|
||||
fn String String.trim(String string, String to_trim = "\t\n\r ")
|
||||
fn String String.trim(string, String to_trim = "\t\n\r ")
|
||||
{
|
||||
usz start = 0;
|
||||
usz len = string.len;
|
||||
@@ -100,7 +100,7 @@ fn String String.trim(String string, String to_trim = "\t\n\r ")
|
||||
* @param [in] string
|
||||
* @param [in] needle
|
||||
**/
|
||||
fn bool String.starts_with(String string, String needle)
|
||||
fn bool String.starts_with(string, String needle)
|
||||
{
|
||||
if (needle.len > string.len) return false;
|
||||
if (!needle.len) return true;
|
||||
@@ -111,7 +111,7 @@ fn bool String.starts_with(String string, String needle)
|
||||
* @param [in] string
|
||||
* @param [in] needle
|
||||
**/
|
||||
fn bool String.ends_with(String string, String needle)
|
||||
fn bool String.ends_with(string, String needle)
|
||||
{
|
||||
if (needle.len > string.len) return false;
|
||||
if (!needle.len) return true;
|
||||
@@ -124,7 +124,7 @@ fn bool String.ends_with(String string, String needle)
|
||||
* @param [in] string
|
||||
* @param [in] needle
|
||||
**/
|
||||
fn String String.strip(String string, String needle)
|
||||
fn String String.strip(string, String needle)
|
||||
{
|
||||
if (!needle.len || !string.starts_with(needle)) return string;
|
||||
return string[needle.len..];
|
||||
@@ -136,7 +136,7 @@ fn String String.strip(String string, String needle)
|
||||
* @param [in] string
|
||||
* @param [in] needle
|
||||
**/
|
||||
fn String String.strip_end(String string, String needle)
|
||||
fn String String.strip_end(string, String needle)
|
||||
{
|
||||
if (!needle.len || !string.ends_with(needle)) return string;
|
||||
// Note that this is the safe way if we want to support zero length.
|
||||
@@ -154,7 +154,7 @@ fn String String.strip_end(String string, String needle)
|
||||
* @require needle.len > 0 "The needle must be at least 1 character long"
|
||||
* @ensure return.len > 0
|
||||
**/
|
||||
fn String[] String.split(String s, String needle, usz max = 0, Allocator* using = mem::heap())
|
||||
fn String[] String.split(s, String needle, usz max = 0, Allocator* using = mem::heap())
|
||||
{
|
||||
usz capacity = 16;
|
||||
usz i = 0;
|
||||
@@ -192,12 +192,12 @@ fn String[] String.split(String s, String needle, usz max = 0, Allocator* using
|
||||
* @param [in] needle
|
||||
* @param max "Max number of elements, 0 means no limit, defaults to 0"
|
||||
**/
|
||||
fn String[] String.tsplit(String s, String needle, usz max = 0)
|
||||
fn String[] String.tsplit(s, String needle, usz max = 0)
|
||||
{
|
||||
return s.split(needle, max, mem::temp()) @inline;
|
||||
}
|
||||
|
||||
fn bool String.contains(String s, String needle)
|
||||
fn bool String.contains(s, String needle)
|
||||
{
|
||||
return @ok(s.index_of(needle));
|
||||
}
|
||||
@@ -213,7 +213,7 @@ fn bool String.contains(String s, String needle)
|
||||
* @return "the index of the needle"
|
||||
* @return! SearchResult.MISSING "if the needle cannot be found"
|
||||
**/
|
||||
fn usz! String.index_of(String s, String needle)
|
||||
fn usz! String.index_of(s, String needle)
|
||||
{
|
||||
usz match = 0;
|
||||
usz needed = needle.len;
|
||||
@@ -249,7 +249,7 @@ fn usz! String.index_of(String s, String needle)
|
||||
* @return "the index of the needle"
|
||||
* @return! SearchResult.MISSING "if the needle cannot be found"
|
||||
**/
|
||||
fn usz! String.rindex_of(String s, String needle)
|
||||
fn usz! String.rindex_of(s, String needle)
|
||||
{
|
||||
usz match = 0;
|
||||
usz needed = needle.len;
|
||||
@@ -274,12 +274,12 @@ fn usz! String.rindex_of(String s, String needle)
|
||||
return SearchResult.MISSING?;
|
||||
}
|
||||
|
||||
fn String ZString.as_str(ZString str)
|
||||
fn String ZString.as_str(str)
|
||||
{
|
||||
return (String)((char*)str)[:str.len()];
|
||||
}
|
||||
|
||||
fn usz ZString.char_len(ZString str)
|
||||
fn usz ZString.char_len(str)
|
||||
{
|
||||
usz len = 0;
|
||||
char* ptr = (char*)str;
|
||||
@@ -290,7 +290,7 @@ fn usz ZString.char_len(ZString str)
|
||||
return len;
|
||||
}
|
||||
|
||||
fn usz ZString.len(ZString str)
|
||||
fn usz ZString.len(str)
|
||||
{
|
||||
usz len = 0;
|
||||
char* ptr = (char*)str;
|
||||
@@ -299,7 +299,7 @@ fn usz ZString.len(ZString str)
|
||||
}
|
||||
|
||||
|
||||
fn ZString String.zstr_copy(String s, Allocator* using = mem::heap())
|
||||
fn ZString String.zstr_copy(s, Allocator* using = mem::heap())
|
||||
{
|
||||
usz len = s.len;
|
||||
char* str = malloc(len + 1, .using = using);
|
||||
@@ -308,7 +308,7 @@ fn ZString String.zstr_copy(String s, Allocator* using = mem::heap())
|
||||
return (ZString)str;
|
||||
}
|
||||
|
||||
fn String String.concat(String s1, String s2, Allocator* using = mem::heap())
|
||||
fn String String.concat(s1, String s2, Allocator* using = mem::heap())
|
||||
{
|
||||
usz full_len = s1.len + s2.len;
|
||||
char* str = malloc(full_len + 1, .using = using);
|
||||
@@ -319,12 +319,12 @@ fn String String.concat(String s1, String s2, Allocator* using = mem::heap())
|
||||
return (String)str[:full_len];
|
||||
}
|
||||
|
||||
fn String String.tconcat(String s1, String s2) => s1.concat(s2, mem::temp());
|
||||
fn String String.tconcat(s1, String s2) => s1.concat(s2, mem::temp());
|
||||
|
||||
|
||||
fn ZString String.zstr_tcopy(String s) => s.zstr_copy(mem::temp()) @inline;
|
||||
fn ZString String.zstr_tcopy(s) => s.zstr_copy(mem::temp()) @inline;
|
||||
|
||||
fn String String.copy(String s, Allocator* using = mem::heap())
|
||||
fn String String.copy(s, Allocator* using = mem::heap())
|
||||
{
|
||||
usz len = s.len;
|
||||
char* str = malloc(len + 1, .using = using);
|
||||
@@ -333,10 +333,10 @@ fn String String.copy(String s, Allocator* using = mem::heap())
|
||||
return (String)str[:len];
|
||||
}
|
||||
|
||||
fn String String.tcopy(String s) => s.copy(mem::temp()) @inline;
|
||||
fn String String.tcopy(s) => s.copy(mem::temp()) @inline;
|
||||
|
||||
fn String ZString.copy(ZString z, Allocator* using = mem::heap()) => z.as_str().copy(using) @inline;
|
||||
fn String ZString.tcopy(ZString z) => z.as_str().copy(mem::temp()) @inline;
|
||||
fn String ZString.copy(z, Allocator* using = mem::heap()) => z.as_str().copy(using) @inline;
|
||||
fn String ZString.tcopy(z) => z.as_str().copy(mem::temp()) @inline;
|
||||
|
||||
/**
|
||||
* Convert an UTF-8 string to UTF-16
|
||||
@@ -344,7 +344,7 @@ fn String ZString.tcopy(ZString z) => z.as_str().copy(mem::temp()) @inline;
|
||||
* @return! UnicodeResult.INVALID_UTF8 "If the string contained an invalid UTF-8 sequence"
|
||||
* @return! AllocationFailure "If allocation of the string fails"
|
||||
**/
|
||||
fn Char16[]! String.to_utf16(String s, Allocator* using = mem::heap())
|
||||
fn Char16[]! String.to_utf16(s, Allocator* using = mem::heap())
|
||||
{
|
||||
usz len16 = conv::utf16len_for_utf8(s);
|
||||
Char16* data = malloc_checked(Char16, len16 + 1, .using = using)!;
|
||||
@@ -353,9 +353,9 @@ fn Char16[]! String.to_utf16(String s, Allocator* using = mem::heap())
|
||||
return data[:len16];
|
||||
}
|
||||
|
||||
fn WString! String.to_wstring(String s, Allocator* using = mem::heap()) => (WString)s.to_utf16(using).ptr;
|
||||
fn WString! String.to_wstring(s, Allocator* using = mem::heap()) => (WString)s.to_utf16(using).ptr;
|
||||
|
||||
fn Char32[]! String.to_utf32(String s, Allocator* using = mem::heap())
|
||||
fn Char32[]! String.to_utf32(s, Allocator* using = mem::heap())
|
||||
{
|
||||
usz codepoints = conv::utf8_codepoints(s);
|
||||
Char32* data = malloc_checked(Char32, codepoints + 1, .using = using)!;
|
||||
@@ -364,24 +364,24 @@ fn Char32[]! String.to_utf32(String s, Allocator* using = mem::heap())
|
||||
return data[:codepoints];
|
||||
}
|
||||
|
||||
fn void String.convert_ascii_to_lower(String s)
|
||||
fn void String.convert_ascii_to_lower(s)
|
||||
{
|
||||
foreach (&c : s) if (*c >= 'A' && *c <= 'Z') *c += 'a' - 'A';
|
||||
}
|
||||
|
||||
fn String String.ascii_to_lower(String s, Allocator* using = mem::heap())
|
||||
fn String String.ascii_to_lower(s, Allocator* using = mem::heap())
|
||||
{
|
||||
String copy = s.copy(using);
|
||||
copy.convert_ascii_to_lower();
|
||||
return copy;
|
||||
}
|
||||
|
||||
fn void String.convert_ascii_to_upper(String s)
|
||||
fn void String.convert_ascii_to_upper(s)
|
||||
{
|
||||
foreach (&c : s) if (*c >= 'a' && *c <= 'z') *c -= 'a' - 'A';
|
||||
}
|
||||
|
||||
fn String String.ascii_to_upper(String s, Allocator* using = mem::heap())
|
||||
fn String String.ascii_to_upper(s, Allocator* using = mem::heap())
|
||||
{
|
||||
String copy = s.copy(using);
|
||||
copy.convert_ascii_to_upper();
|
||||
|
||||
@@ -6,18 +6,18 @@ struct StringIterator
|
||||
usz current;
|
||||
}
|
||||
|
||||
fn void StringIterator.reset(StringIterator* this)
|
||||
fn void StringIterator.reset(&self)
|
||||
{
|
||||
this.current = 0;
|
||||
self.current = 0;
|
||||
}
|
||||
|
||||
fn Char32! StringIterator.next(StringIterator* this)
|
||||
fn Char32! StringIterator.next(&self)
|
||||
{
|
||||
usz len = this.utf8.len;
|
||||
usz current = this.current;
|
||||
usz len = self.utf8.len;
|
||||
usz current = self.current;
|
||||
if (current >= len) return IteratorResult.NO_MORE_ELEMENT?;
|
||||
usz read = (len - current < 4 ? len - current : 4);
|
||||
Char32 res = conv::utf8_to_char32(&this.utf8[current], &read)!;
|
||||
this.current += read;
|
||||
Char32 res = conv::utf8_to_char32(&self.utf8[current], &read)!;
|
||||
self.current += read;
|
||||
return res;
|
||||
}
|
||||
@@ -449,7 +449,7 @@ macro double! hexfloat(char[] chars, int $bits, int $emin, int sign)
|
||||
return math::scalbn(y, (int)e2);
|
||||
}
|
||||
|
||||
macro String.to_real(String chars, $Type) @private
|
||||
macro String.to_real(chars, $Type) @private
|
||||
{
|
||||
int sign = 1;
|
||||
$switch ($Type)
|
||||
|
||||
@@ -85,7 +85,7 @@ macro bool is_numerical($Type)
|
||||
$endif
|
||||
}
|
||||
|
||||
fn bool TypeKind.is_int(TypeKind kind) @inline
|
||||
fn bool TypeKind.is_int(kind) @inline
|
||||
{
|
||||
return kind == TypeKind.SIGNED_INT || kind == TypeKind.UNSIGNED_INT;
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ fault IoError
|
||||
OUT_OF_SPACE,
|
||||
INVALID_PUSHBACK,
|
||||
EOF,
|
||||
UNEXPECTED_EOF,
|
||||
CANNOT_READ_DIR,
|
||||
TOO_MANY_DESCRIPTORS,
|
||||
FILE_IS_DIR,
|
||||
|
||||
@@ -121,7 +121,7 @@ macro bool! Formatter.print_with_function(&self, any arg)
|
||||
self.width = old_width;
|
||||
self.prec = old_prec;
|
||||
}
|
||||
arg.to_format(&self)!; // TODO should be self
|
||||
arg.to_format(&self)!;
|
||||
return true;
|
||||
}
|
||||
if (&arg.to_string)
|
||||
|
||||
@@ -104,6 +104,13 @@ fn char! Stream.read_byte(self) @inline
|
||||
return IoError.UNSUPPORTED_OPERATION?;
|
||||
}
|
||||
|
||||
fn usz! Stream.read_all(self, char[] buffer) @inline
|
||||
{
|
||||
usz n = self.read(buffer)!;
|
||||
if (n != buffer.len) return IoError.UNEXPECTED_EOF?;
|
||||
return n;
|
||||
}
|
||||
|
||||
fn String! Stream.readline(self, Allocator* using = mem::heap())
|
||||
{
|
||||
ReadByteStreamFn func;
|
||||
|
||||
Reference in New Issue
Block a user