From 7dc1eab1859a1f1e1719bfb3b7a38c2352266557 Mon Sep 17 00:00:00 2001 From: Pierre Curto Date: Fri, 7 Jul 2023 13:51:44 +0200 Subject: [PATCH] std/lib/collections: make List support the []= operator (#831) * std/lib/collections: make List support the []= operator Signed-off-by: Pierre Curto * std/lib/io: rename receiver to self Signed-off-by: Pierre Curto --------- Signed-off-by: Pierre Curto --- lib/std/collections/list.c3 | 5 + lib/std/io/io_file.c3 | 16 +- lib/std/io/io_formatter_private.c3 | 196 ++++++++++++------------ lib/std/io/io_printf.c3 | 220 +++++++++++++-------------- lib/std/io/io_stream.c3 | 128 ++++++++-------- lib/std/io/stream/buffer.c3 | 105 +++++++------ lib/std/io/stream/bytereader.c3 | 52 +++---- lib/std/io/stream/bytewriter.c3 | 90 +++++------ lib/std/io/stream/dstringwriter.c3 | 4 +- lib/std/io/stream/filestream.c3 | 4 +- test/unit/stdlib/collections/list.c3 | 4 +- 11 files changed, 418 insertions(+), 406 deletions(-) diff --git a/lib/std/collections/list.c3 b/lib/std/collections/list.c3 index f16a4c7a4..0aac53f65 100644 --- a/lib/std/collections/list.c3 +++ b/lib/std/collections/list.c3 @@ -290,6 +290,11 @@ fn Type* List.get_ref(&self, usz index) @operator(&[]) @inline return &self.entries[index]; } +fn void List.set(&self, usz index, Type value) @operator([]=) +{ + self.entries[index] = value; +} + fn void List.ensure_capacity(&self, usz added = 1) @inline @private { usz new_size = self.size + added; diff --git a/lib/std/io/io_file.c3 b/lib/std/io/io_file.c3 index 21f9b03e3..cae621559 100644 --- a/lib/std/io/io_file.c3 +++ b/lib/std/io/io_file.c3 @@ -19,27 +19,27 @@ fn File from_libc(CFile file) } /** - * @require file.file != null + * @require self.file != null **/ -fn void! File.reopen(File* file, String filename, String mode) +fn void! File.reopen(&self, String filename, String mode) { - file.file = os::native_freopen(file.file, filename, mode)!; + self.file = os::native_freopen(self.file, filename, mode)!; } /** - * @require file.file != null + * @require self.file != null **/ -fn usz! File.seek(File file, isz offset, Seek seek_mode = Seek.SET) +fn usz! File.seek(self, isz offset, Seek seek_mode = Seek.SET) { - os::native_fseek(file.file, offset, seek_mode)!; - return os::native_ftell(file.file); + os::native_fseek(self.file, offset, seek_mode)!; + return os::native_ftell(self.file); } /* Implement later /** - * @require file.file == null + * @require self.file == null **/ fn void! File.memopen(File* file, char[] data, String mode) { diff --git a/lib/std/io/io_formatter_private.c3 b/lib/std/io/io_formatter_private.c3 index 52c103e05..63cf5b407 100644 --- a/lib/std/io/io_formatter_private.c3 +++ b/lib/std/io/io_formatter_private.c3 @@ -3,16 +3,16 @@ module std::io; const char[16] XDIGITS_H = "0123456789ABCDEF"; const char[16] XDIGITS_L = "0123456789abcdef"; -fn void! Formatter.left_adjust(Formatter* this, usz len) @local +fn void! Formatter.left_adjust(&self, usz len) @local { - if (!this.flags.left) return; - for (usz l = len; l < this.width; l++) this.out(' ')!; + if (!self.flags.left) return; + for (usz l = len; l < self.width; l++) self.out(' ')!; } -fn void! Formatter.right_adjust(Formatter* this, usz len) @local +fn void! Formatter.right_adjust(&self, usz len) @local { - if (this.flags.left) return; - for (usz l = len; l < this.width; l++) this.out(' ')!; + if (self.flags.left) return; + for (usz l = len; l < self.width; l++) self.out(' ')!; } @@ -136,12 +136,12 @@ fn uint simple_atoi(char* buf, usz maxlen, usz* len_ptr) @inline @private return i; } -fn void! Formatter.out_substr(Formatter *this, String str) @private +fn void! Formatter.out_substr(&self, String str) @private { usz l = conv::utf8_codepoints(str); - uint prec = this.prec; - if (this.flags.precision && l < prec) l = prec; - this.right_adjust(' ')!; + uint prec = self.prec; + if (self.flags.precision && l < prec) l = prec; + self.right_adjust(' ')!; usz index = 0; usz chars = str.len; char* ptr = str.ptr; @@ -149,16 +149,16 @@ fn void! Formatter.out_substr(Formatter *this, String str) @private { char c = ptr[index]; // Break if we have precision set and we ran out... - if (c & 0xC0 != 0x80 && this.flags.precision && !prec--) break; - this.out(c)!; + if (c & 0xC0 != 0x80 && self.flags.precision && !prec--) break; + self.out(c)!; index++; } - return this.left_adjust(l); + return self.left_adjust(l); } -fn void! Formatter.pad(Formatter* this, char c, isz width, isz len) @inline +fn void! Formatter.pad(&self, char c, isz width, isz len) @inline { - for (isz i = len; i < width; i++) this.out(c)!; + for (isz i = len; i < width; i++) self.out(c)!; } fn char* fmt_u(uint128 x, char* s) @@ -168,9 +168,9 @@ fn char* fmt_u(uint128 x, char* s) return s; } -fn void! Formatter.out_chars(Formatter* this, char[] s) +fn void! Formatter.out_chars(&self, char[] s) { - foreach (c : s) this.out(c)!; + foreach (c : s) self.out(c)!; } enum FloatFormatting @@ -181,12 +181,12 @@ enum FloatFormatting HEX } -fn void! Formatter.etoa(Formatter* this, double y) => this.floatformat(EXPONENTIAL, y); -fn void! Formatter.ftoa(Formatter* this, double y) => this.floatformat(FLOAT, y); -fn void! Formatter.gtoa(Formatter* this, double y) => this.floatformat(ADAPTIVE, y); -fn void! Formatter.atoa(Formatter* this, double y) => this.floatformat(HEX, y); +fn void! Formatter.etoa(&self, double y) => self.floatformat(EXPONENTIAL, y); +fn void! Formatter.ftoa(&self, double y) => self.floatformat(FLOAT, y); +fn void! Formatter.gtoa(&self, double y) => self.floatformat(ADAPTIVE, y); +fn void! Formatter.atoa(&self, double y) => self.floatformat(HEX, y); -fn void! Formatter.floatformat(Formatter* this, FloatFormatting formatting, double y) @private +fn void! Formatter.floatformat(&self, FloatFormatting formatting, double y) @private { // This code is heavily based on musl's printf code const BUF_SIZE = (math::DOUBLE_MANT_DIG + 28) / 29 + 1 @@ -198,17 +198,17 @@ fn void! Formatter.floatformat(Formatter* this, FloatFormatting formatting, doub is_neg = true; y = -y; } - int pl = is_neg || this.flags.plus ? 1 : 0; + int pl = is_neg || self.flags.plus ? 1 : 0; // Print inf/nan if (!math::is_finite(y)) { // Add padding - if (!this.flags.left) this.pad(' ', this.width, 3 + pl)!; - String s = this.flags.uppercase ? "INF" : "inf"; - if (y != y) this.flags.uppercase ? "NAN" : "nan"; - if (pl) this.out(is_neg ? '-' : '+')!; - this.out_chars(s)!; - if (this.flags.left) this.pad(' ', this.width, 3 + pl)!; + if (!self.flags.left) self.pad(' ', self.width, 3 + pl)!; + String s = self.flags.uppercase ? "INF" : "inf"; + if (y != y) self.flags.uppercase ? "NAN" : "nan"; + if (pl) self.out(is_neg ? '-' : '+')!; + self.out_chars(s)!; + if (self.flags.left) self.pad(' ', self.width, 3 + pl)!; return; } // Rescale @@ -220,7 +220,7 @@ fn void! Formatter.floatformat(Formatter* this, FloatFormatting formatting, doub char* ebuf = 12 + (char*)&ebuf0; char[9 + math::DOUBLE_MANT_DIG / 4] buf_array; char* buf = &buf_array; - isz p = this.flags.precision ? this.prec : -1; + isz p = self.flags.precision ? self.prec : -1; if (formatting == HEX) { double round = 8.0; @@ -248,15 +248,15 @@ fn void! Formatter.floatformat(Formatter* this, FloatFormatting formatting, doub char* estr = fmt_u(e2 < 0 ? (int128)-e2 : (int128)e2, ebuf); if (estr == ebuf) *--estr = '0'; *--estr = (e2 < 0 ? '-' : '+'); - *--estr = this.flags.uppercase ? 'P' : 'p'; + *--estr = self.flags.uppercase ? 'P' : 'p'; char* s = buf; - char* xdigits = this.flags.uppercase ? &XDIGITS_H : &XDIGITS_L; + char* xdigits = self.flags.uppercase ? &XDIGITS_H : &XDIGITS_L; do { int x = (int)y; *s++ = xdigits[x]; y = 16 * (y - x); - if (s - buf == 1 && (y || p > 0 || this.flags.hash)) *s++ = '.'; + if (s - buf == 1 && (y || p > 0 || self.flags.hash)) *s++ = '.'; } while (y); isz outlen = s - buf; isz explen = ebuf - estr; @@ -264,14 +264,14 @@ fn void! Formatter.floatformat(Formatter* this, FloatFormatting formatting, doub usz l = p && outlen - 2 < p ? p + 2 + explen : outlen + explen; - if (!this.flags.left && !this.flags.zeropad) this.pad(' ', this.width, pl + l)!; - if (is_neg || this.flags.plus) this.out(is_neg ? '-' : '+')!; - this.out_chars(this.flags.uppercase ? "0X" : "0x")!; - if (this.flags.zeropad) this.pad('0', this.width, pl + l)!; - this.out_chars(buf[:outlen])!; - this.pad('0', l - outlen - explen, 0)!; - this.out_chars(estr[:explen])!; - if (this.flags.left) this.pad(' ', this.width, pl + l)!; + if (!self.flags.left && !self.flags.zeropad) self.pad(' ', self.width, pl + l)!; + if (is_neg || self.flags.plus) self.out(is_neg ? '-' : '+')!; + self.out_chars(self.flags.uppercase ? "0X" : "0x")!; + if (self.flags.zeropad) self.pad('0', self.width, pl + l)!; + self.out_chars(buf[:outlen])!; + self.pad('0', l - outlen - explen, 0)!; + self.out_chars(estr[:explen])!; + if (self.flags.left) self.pad(' ', self.width, pl + l)!; return; } if (p < 0) p = 6; @@ -405,7 +405,7 @@ fn void! Formatter.floatformat(Formatter* this, FloatFormatting formatting, doub formatting = EXPONENTIAL; p--; } - if (!this.flags.hash) + if (!self.flags.hash) { // Count trailing zeros in last place if (z > a && z[-1]) @@ -427,8 +427,8 @@ fn void! Formatter.floatformat(Formatter* this, FloatFormatting formatting, doub } } } - if (p > int.max - 1 - (isz)(p || this.flags.hash)) return PrintFault.INTERNAL_BUFFER_EXCEEDED?; - int l = (int)(1 + p + (isz)(p || this.flags.hash)); + if (p > int.max - 1 - (isz)(p || self.flags.hash)) return PrintFault.INTERNAL_BUFFER_EXCEEDED?; + int l = (int)(1 + p + (isz)(p || self.flags.hash)); char* estr @noinit; if (formatting == FLOAT) { @@ -440,14 +440,14 @@ fn void! Formatter.floatformat(Formatter* this, FloatFormatting formatting, doub estr = fmt_u((uint128)(e < 0 ? -e : e), ebuf); while (ebuf - estr < 2) (--estr)[0] = '0'; *--estr = (e < 0 ? '-' : '+'); - *--estr = this.flags.uppercase ? 'E' : 'e'; + *--estr = self.flags.uppercase ? 'E' : 'e'; if (ebuf - estr > (isz)int.max - l) return PrintFault.INTERNAL_BUFFER_EXCEEDED?; l += (int)(ebuf - estr); } if (l > int.max - pl) return PrintFault.INTERNAL_BUFFER_EXCEEDED?; - if (!this.flags.left && !this.flags.zeropad) this.pad(' ', this.width, pl + l)!; - if (is_neg || this.flags.plus) this.out(is_neg ? '-' : '+')!; - if (this.flags.zeropad) this.pad('0', this.width, pl + l)!; + if (!self.flags.left && !self.flags.zeropad) self.pad(' ', self.width, pl + l)!; + if (is_neg || self.flags.plus) self.out(is_neg ? '-' : '+')!; + if (self.flags.zeropad) self.pad('0', self.width, pl + l)!; if (formatting == FLOAT) { if (a > r) a = r; @@ -462,16 +462,16 @@ fn void! Formatter.floatformat(Formatter* this, FloatFormatting formatting, doub case s == buf + 9: *--s = '0'; } - this.out_chars(s[:buf + 9 - s])!; + self.out_chars(s[:buf + 9 - s])!; } - if (p || this.flags.hash) this.out('.')!; + if (p || self.flags.hash) self.out('.')!; for (; d < z && p > 0; d++, p -= 9) { char* s = fmt_u(*d, buf + 9); while (s > buf) *--s = '0'; - this.out_chars(s[:math::min((isz)9, p)])!; + self.out_chars(s[:math::min((isz)9, p)])!; } - this.pad('0', p + 9, 9)!; + self.pad('0', p + 9, 9)!; } else { @@ -486,33 +486,33 @@ fn void! Formatter.floatformat(Formatter* this, FloatFormatting formatting, doub } else { - this.out(s++[0])!; - if (p > 0 || this.flags.hash) this.out('.')!; + self.out(s++[0])!; + if (p > 0 || self.flags.hash) self.out('.')!; } - this.out_chars(s[:math::min(buf + 9 - s, p)])!; + self.out_chars(s[:math::min(buf + 9 - s, p)])!; p -= buf + 9 - s; } - this.pad('0', p + 18, 18)!; - this.out_chars(estr[:ebuf - estr])!; + self.pad('0', p + 18, 18)!; + self.out_chars(estr[:ebuf - estr])!; } - if (this.flags.left) this.pad(' ', this.width, pl + l)!; + if (self.flags.left) self.pad(' ', self.width, pl + l)!; return; } -fn void! Formatter.ntoa(Formatter* this, uint128 value, bool negative, uint base) @private +fn void! Formatter.ntoa(&self, uint128 value, bool negative, uint base) @private { char[PRINTF_NTOA_BUFFER_SIZE] buf @noinit; usz len = 0; // no hash for 0 values - if (!value) this.flags.hash = false; + if (!value) self.flags.hash = false; // write if precision != 0 or value is != 0 - if (!this.flags.precision || value) + if (!self.flags.precision || value) { - char past_10 = (this.flags.uppercase ? 'A' : 'a') - 10; + char past_10 = (self.flags.uppercase ? 'A' : 'a') - 10; do { if (len >= PRINTF_NTOA_BUFFER_SIZE) return PrintFault.INTERNAL_BUFFER_EXCEEDED?; @@ -522,21 +522,21 @@ fn void! Formatter.ntoa(Formatter* this, uint128 value, bool negative, uint base } while (value); } - return this.ntoa_format((String)buf[:PRINTF_NTOA_BUFFER_SIZE], len, negative, base); + return self.ntoa_format((String)buf[:PRINTF_NTOA_BUFFER_SIZE], len, negative, base); } -fn void! Formatter.ntoa_format(Formatter* this, String buf, usz len, bool negative, uint base) @private +fn void! Formatter.ntoa_format(&self, String buf, usz len, bool negative, uint base) @private { // pad leading zeros - if (!this.flags.left) + if (!self.flags.left) { - if (this.width && this.flags.zeropad && (negative || this.flags.plus || this.flags.space)) this.width--; - while (len < this.prec) + if (self.width && self.flags.zeropad && (negative || self.flags.plus || self.flags.space)) self.width--; + while (len < self.prec) { if (len >= buf.len) return PrintFault.INTERNAL_BUFFER_EXCEEDED?; buf[len++] = '0'; } - while (this.flags.zeropad && len < this.width) + while (self.flags.zeropad && len < self.width) { if (len >= buf.len) return PrintFault.INTERNAL_BUFFER_EXCEEDED?; buf[len++] = '0'; @@ -544,9 +544,9 @@ fn void! Formatter.ntoa_format(Formatter* this, String buf, usz len, bool negati } // handle hash - if (this.flags.hash && base != 10) + if (self.flags.hash && base != 10) { - if (!this.flags.precision && len && len == this.prec && len == this.width) + if (!self.flags.precision && len && len == self.prec && len == self.width) { len--; if (len) len--; @@ -557,11 +557,11 @@ fn void! Formatter.ntoa_format(Formatter* this, String buf, usz len, bool negati switch (base) { case 16: - buf[len++] = this.flags.uppercase ? 'X' : 'x'; + buf[len++] = self.flags.uppercase ? 'X' : 'x'; case 8: - buf[len++] = this.flags.uppercase ? 'O' : 'o'; + buf[len++] = self.flags.uppercase ? 'O' : 'o'; case 2: - buf[len++] = this.flags.uppercase ? 'B' : 'b'; + buf[len++] = self.flags.uppercase ? 'B' : 'b'; default: unreachable(); } @@ -574,70 +574,70 @@ fn void! Formatter.ntoa_format(Formatter* this, String buf, usz len, bool negati case negative: if (len >= buf.len) return PrintFault.INTERNAL_BUFFER_EXCEEDED?; buf[len++] = '-'; - case this.flags.plus: + case self.flags.plus: if (len >= buf.len) return PrintFault.INTERNAL_BUFFER_EXCEEDED?; buf[len++] = '+'; - case this.flags.space: + case self.flags.space: if (len >= buf.len) return PrintFault.INTERNAL_BUFFER_EXCEEDED?; buf[len++] = ' '; } if (!len) return; - return this.out_reverse(buf[:len]); + return self.out_reverse(buf[:len]); } -fn void! Formatter.ntoa_any(Formatter* this, any arg, uint base) @private +fn void! Formatter.ntoa_any(&self, any arg, uint base) @private { bool is_neg; uint128 val = int_from_any(arg, &is_neg)!!; - return this.ntoa(val, is_neg, base) @inline; + return self.ntoa(val, is_neg, base) @inline; } -fn void! Formatter.out_char(Formatter* this, any arg) @private +fn void! Formatter.out_char(&self, any arg) @private { uint l = 1; // pre padding - this.right_adjust(l)!; + self.right_adjust(l)!; // char output Char32 c = types::any_to_int(arg, uint) ?? 0xFFFD; switch (true) { case c < 0x7f: - this.out((char)c)!; + self.out((char)c)!; case c < 0x7ff: - this.out((char)(0xC0 | c >> 6))!; - this.out((char)(0x80 | (c & 0x3F)))!; + self.out((char)(0xC0 | c >> 6))!; + self.out((char)(0x80 | (c & 0x3F)))!; case c < 0xffff: - this.out((char)(0xE0 | c >> 12))!; - this.out((char)(0x80 | (c >> 6 & 0x3F)))!; - this.out((char)(0x80 | (c & 0x3F)))!; + self.out((char)(0xE0 | c >> 12))!; + self.out((char)(0x80 | (c >> 6 & 0x3F)))!; + self.out((char)(0x80 | (c & 0x3F)))!; default: - this.out((char)(0xF0 | c >> 18))!; - this.out((char)(0x80 | (c >> 12 & 0x3F)))!; - this.out((char)(0x80 | (c >> 6 & 0x3F)))!; - this.out((char)(0x80 | (c & 0x3F)))!; + self.out((char)(0xF0 | c >> 18))!; + self.out((char)(0x80 | (c >> 12 & 0x3F)))!; + self.out((char)(0x80 | (c >> 6 & 0x3F)))!; + self.out((char)(0x80 | (c & 0x3F)))!; } - return this.left_adjust(l); + return self.left_adjust(l); } -fn void! Formatter.out_reverse(Formatter* this, char[] buf) @private +fn void! Formatter.out_reverse(&self, char[] buf) @private { - usz buffer_start_idx = this.idx; + usz buffer_start_idx = self.idx; usz len = buf.len; // pad spaces up to given width - if (!this.flags.left && !this.flags.zeropad) + if (!self.flags.left && !self.flags.zeropad) { - for (usz i = len; i < this.width; i++) + for (usz i = len; i < self.width; i++) { - this.out(' ')!; + self.out(' ')!; } } // reverse string - while (len) this.out(buf[--len])!; + while (len) self.out(buf[--len])!; // append pad spaces up to given width - return this.left_adjust(this.idx - buffer_start_idx); + return self.left_adjust(self.idx - buffer_start_idx); } fn void! printf_advance_format(usz format_len, usz *index_ptr) @inline @private diff --git a/lib/std/io/io_printf.c3 b/lib/std/io/io_printf.c3 index 23f6a5575..b211ebeff 100644 --- a/lib/std/io/io_printf.c3 +++ b/lib/std/io/io_printf.c3 @@ -52,26 +52,26 @@ fn char[]! bprintf(char[] buffer, String format, args...) @maydiscard return buffer[:data.written]; } -fn usz! File.printf(File file, String format, args...) @maydiscard +fn usz! File.printf(self, String format, args...) @maydiscard { Formatter formatter; - formatter.init(&out_fputchar_fn, &file); + formatter.init(&out_fputchar_fn, &self); return formatter.vprintf(format, args)!; } -fn usz! File.printfn(File file, String format, args...) @maydiscard +fn usz! File.printfn(self, String format, args...) @maydiscard { Formatter formatter; - formatter.init(&out_fputchar_fn, &file); + formatter.init(&out_fputchar_fn, &self); usz len = formatter.vprintf(format, args)!; - file.putc('\n')!; - file.flush(); + self.putc('\n')!; + self.flush(); return len + 1; } -fn usz! Formatter.printf(Formatter* this, String format, args...) +fn usz! Formatter.printf(&self, String format, args...) { - return this.vprintf(format, args) @inline; + return self.vprintf(format, args) @inline; } struct Formatter @@ -98,46 +98,46 @@ bitstruct PrintFlags : uint bool precision : 6; } -fn void Formatter.init(Formatter* this, OutputFn out_fn, void* data = null) +fn void Formatter.init(&self, OutputFn out_fn, void* data = null) { - *this = { .data = data, .out_fn = out_fn}; + *self = { .data = data, .out_fn = out_fn}; } -fn void! Formatter.out(Formatter* this, char c) @private +fn void! Formatter.out(&self, char c) @private { - this.out_fn(c, this.data)!; + self.out_fn(c, self.data)!; } -macro bool! Formatter.print_with_function(Formatter* this, any arg) +macro bool! Formatter.print_with_function(&self, any arg) { if (&arg.to_format) { - PrintFlags old = this.flags; - uint old_width = this.width; - uint old_prec = this.prec; + PrintFlags old = self.flags; + uint old_width = self.width; + uint old_prec = self.prec; defer { - this.flags = old; - this.width = old_width; - this.prec = old_prec; + self.flags = old; + self.width = old_width; + self.prec = old_prec; } - arg.to_format(this)!; + arg.to_format(&self)!; // TODO should be self return true; } if (&arg.to_string) { - PrintFlags old = this.flags; - uint old_width = this.width; - uint old_prec = this.prec; + PrintFlags old = self.flags; + uint old_width = self.width; + uint old_prec = self.prec; defer { - this.flags = old; - this.width = old_width; - this.prec = old_prec; + self.flags = old; + self.width = old_width; + self.prec = old_prec; } @stack_mem(512; Allocator* mem) { - this.out_substr(arg.to_string(mem))!; + self.out_substr(arg.to_string(mem))!; return true; }; } @@ -145,109 +145,109 @@ macro bool! Formatter.print_with_function(Formatter* this, any arg) } -fn void! Formatter.out_str(Formatter* this, any arg) @private +fn void! Formatter.out_str(&self, any arg) @private { switch (arg.type.kindof) { case TYPEID: - return this.out_substr("typeid"); + return self.out_substr("typeid"); case VOID: - return this.out_substr("void"); + return self.out_substr("void"); case ANYFAULT: case FAULT: - return this.out_substr((*(anyfault*)arg.ptr).nameof); + return self.out_substr((*(anyfault*)arg.ptr).nameof); case ANY: - return this.out_str(*(any*)arg); + return self.out_str(*(any*)arg); case ENUM: - if (this.print_with_function(arg)!) return; - return this.out_substr(arg.type.names[types::any_to_int(arg, usz)!!]); + if (self.print_with_function(arg)!) return; + return self.out_substr(arg.type.names[types::any_to_int(arg, usz)!!]); case STRUCT: - if (this.print_with_function(arg)!) return; - return this.out_substr(""); + if (self.print_with_function(arg)!) return; + return self.out_substr(""); case UNION: - if (this.print_with_function(arg)!) return; - return this.out_substr(""); + if (self.print_with_function(arg)!) return; + return self.out_substr(""); case BITSTRUCT: - if (this.print_with_function(arg)!) return; - return this.out_substr(""); + if (self.print_with_function(arg)!) return; + return self.out_substr(""); case FUNC: - if (this.print_with_function(arg)!) return; - return this.out_substr(""); + if (self.print_with_function(arg)!) return; + return self.out_substr(""); case OPTIONAL: unreachable(); case DISTINCT: - if (this.print_with_function(arg)!) return; + if (self.print_with_function(arg)!) return; if (arg.type == DString.typeid) { - return this.out_substr(((DString*)arg).str()); + return self.out_substr(((DString*)arg).str()); } - return this.out_str(any { arg.ptr, arg.type.inner }); + return self.out_str(any { arg.ptr, arg.type.inner }); case POINTER: - if (this.print_with_function(arg)!) return; - return this.ntoa_any(arg, 16); + if (self.print_with_function(arg)!) return; + return self.ntoa_any(arg, 16); case SIGNED_INT: case UNSIGNED_INT: - return this.ntoa_any(arg, 10); + return self.ntoa_any(arg, 10); case FLOAT: - return this.ftoa(float_from_any(arg)!!); + return self.ftoa(float_from_any(arg)!!); case ARRAY: - if (this.print_with_function(arg)!) return; + if (self.print_with_function(arg)!) return; // this is SomeType[*] so grab the "SomeType" typeid inner = arg.type.inner; usz size = inner.sizeof; usz len = arg.type.len; // Pretend this is a String void* ptr = (void*)arg.ptr; - this.out('[')!; + self.out('[')!; for (usz i = 0; i < len; i++) { - if (i != 0) this.out_substr(", ")!; - this.out_str(any { ptr, inner })!; + if (i != 0) self.out_substr(", ")!; + self.out_str(any { ptr, inner })!; ptr += size; } - return this.out(']'); + return self.out(']'); case VECTOR: - if (this.print_with_function(arg)!) return; + if (self.print_with_function(arg)!) return; // this is SomeType[*] so grab the "SomeType" typeid inner = arg.type.inner; usz size = inner.sizeof; usz len = arg.type.len; // Pretend this is a String void* ptr = (void*)arg.ptr; - this.out_substr("[<")!; + self.out_substr("[<")!; for (usz i = 0; i < len; i++) { - if (i != 0) this.out_substr(", ")!; - this.out_str(any { ptr, inner })!; + if (i != 0) self.out_substr(", ")!; + self.out_str(any { ptr, inner })!; ptr += size; } - return this.out_substr(">]"); + return self.out_substr(">]"); case SUBARRAY: - if (this.print_with_function(arg)!) return; + if (self.print_with_function(arg)!) return; // this is SomeType[] so grab the "SomeType" typeid inner = arg.type.inner; if (inner == char.typeid) { - return this.out_substr(*(String*)arg); + return self.out_substr(*(String*)arg); } usz size = inner.sizeof; // Pretend this is a String String* temp = (void*)arg.ptr; void* ptr = (void*)temp.ptr; usz len = temp.len; - this.out('[')!; + self.out('[')!; for (usz i = 0; i < len; i++) { - if (i != 0) this.out_substr(", ")!; - this.out_str(any { ptr, inner })!; + if (i != 0) self.out_substr(", ")!; + self.out_str(any { ptr, inner })!; ptr += size; } - this.out(']')!; + self.out(']')!; case BOOL: - return this.out_substr(*(bool*)arg.ptr ? "true" : "false"); + return self.out_substr(*(bool*)arg.ptr ? "true" : "false"); default: - if (this.print_with_function(arg)!) return; - return this.out_substr("Invalid type"); + if (self.print_with_function(arg)!) return; + return self.out_substr("Invalid type"); } } @@ -282,12 +282,12 @@ struct BufferData @private } -fn usz! Formatter.vprintf(Formatter* this, String format, any[] anys) +fn usz! Formatter.vprintf(&self, String format, any[] anys) { - if (!this.out_fn) + if (!self.out_fn) { // use null output function - this.out_fn = &out_null_fn; + self.out_fn = &out_null_fn; } usz format_len = format.len; usz variant_index = 0; @@ -298,7 +298,7 @@ fn usz! Formatter.vprintf(Formatter* this, String format, any[] anys) if (c != '%') { // no - this.out(c)!; + self.out(c)!; continue; } i++; @@ -306,20 +306,20 @@ fn usz! Formatter.vprintf(Formatter* this, String format, any[] anys) c = format[i]; if (c == '%') { - this.out(c)!; + self.out(c)!; continue; } // evaluate flags - this.flags = {}; + self.flags = {}; while FLAG_EVAL: (true) { switch (c) { - case '0': this.flags.zeropad = true; - case '-': this.flags.left = true; - case '+': this.flags.plus = true; - case ' ': this.flags.space = true; - case '#': this.flags.hash = true; + case '0': self.flags.zeropad = true; + case '-': self.flags.left = true; + case '+': self.flags.plus = true; + case ' ': self.flags.space = true; + case '#': self.flags.hash = true; default: break FLAG_EVAL; } if (++i >= format_len) return PrintFault.INVALID_FORMAT_STRING?; @@ -330,18 +330,18 @@ fn usz! Formatter.vprintf(Formatter* this, String format, any[] anys) c = format[i]; if (w < 0) { - this.flags.left = true; + self.flags.left = true; w = -w; } - this.width = w; + self.width = w; // evaluate precision field - this.prec = 0; + self.prec = 0; if (c == '.') { - this.flags.precision = true; + self.flags.precision = true; if (++i >= format_len) return PrintFault.INVALID_FORMAT_STRING?; int prec = printf_parse_format_field(anys.ptr, anys.len, &variant_index, format.ptr, format.len, &i)!; - this.prec = prec < 0 ? 0 : prec; + self.prec = prec < 0 ? 0 : prec; c = format[i]; } @@ -353,91 +353,91 @@ fn usz! Formatter.vprintf(Formatter* this, String format, any[] anys) { case 'd': base = 10; - this.flags.hash = false; + self.flags.hash = false; case 'X' : - this.flags.uppercase = true; + self.flags.uppercase = true; nextcase; case 'x' : base = 16; case 'O': - this.flags.uppercase = true; + self.flags.uppercase = true; nextcase; case 'o' : base = 8; case 'B': - this.flags.uppercase = true; + self.flags.uppercase = true; nextcase; case 'b' : base = 2; case 'A': - this.flags.uppercase = true; + self.flags.uppercase = true; nextcase; case 'a': - this.atoa(float_from_any(current)!!)!; + self.atoa(float_from_any(current)!!)!; continue; case 'F' : - this.flags.uppercase = true; + self.flags.uppercase = true; nextcase; case 'f': - this.ftoa(float_from_any(current)!!)!; + self.ftoa(float_from_any(current)!!)!; continue; case 'E': - this.flags.uppercase = true; + self.flags.uppercase = true; nextcase; case 'e': - this.etoa(float_from_any(current)!!)!; + self.etoa(float_from_any(current)!!)!; continue; case 'G': - this.flags.uppercase = true; + self.flags.uppercase = true; nextcase; case 'g': - this.gtoa(float_from_any(current)!!)!; + self.gtoa(float_from_any(current)!!)!; continue; case 'c': - this.out_char(current)!; + self.out_char(current)!; continue; case 's': - this.out_str(current)!; + self.out_str(current)!; continue; case 'p': - this.flags.zeropad = true; - this.flags.hash = true; + self.flags.zeropad = true; + self.flags.hash = true; base = 16; default: return PrintFault.INVALID_FORMAT_STRING?; } if (base != 10) { - this.flags.plus = false; - this.flags.space = false; + self.flags.plus = false; + self.flags.space = false; } // ignore '0' flag when precision is given - if (this.flags.precision) this.flags.zeropad = false; + if (self.flags.precision) self.flags.zeropad = false; bool is_neg; uint128 v = int_from_any(current, &is_neg)!!; - this.ntoa(v, is_neg, base)!; + self.ntoa(v, is_neg, base)!; } // termination // out((char)0, buffer, idx < maxlen ? idx : maxlen - 1U, maxlen); // return written chars without terminating \0 - return this.idx; + return self.idx; } -fn usz! Formatter.print(Formatter* this, String str) +fn usz! Formatter.print(&self, String str) { - if (!this.out_fn) + if (!self.out_fn) { // use null output function - this.out_fn = &out_null_fn; + self.out_fn = &out_null_fn; } usz len = str.len; for (usz i = 0; i < len; i++) { - this.out(str[i])!; + self.out(str[i])!; } - return this.idx; + return self.idx; } diff --git a/lib/std/io/io_stream.c3 b/lib/std/io/io_stream.c3 index e6460ad1a..14ab3d879 100644 --- a/lib/std/io/io_stream.c3 +++ b/lib/std/io/io_stream.c3 @@ -37,55 +37,55 @@ struct Stream void* data; } -fn bool Stream.supports_flush(Stream s) @inline => (bool)s.fns.flush_fn; -fn bool Stream.supports_seek(Stream s) @inline => (bool)s.fns.seek_fn; -fn bool Stream.supports_available(Stream s) @inline => s.fns.available_fn || s.fns.seek_fn; -fn bool Stream.supports_len(Stream s) @inline => s.fns.len_fn || s.fns.seek_fn; -fn bool Stream.supports_read(Stream s) @inline => s.fns.read_fn || s.fns.read_byte_fn; -fn bool Stream.supports_read_from(Stream s) @inline => (bool)s.fns.read_stream_fn; -fn bool Stream.supports_write_to(Stream s) @inline => (bool)s.fns.write_stream_fn; -fn bool Stream.supports_pushback_byte(Stream s) @inline => s.fns.pushback_byte_fn || s.fns.seek_fn; -fn bool Stream.supports_write(Stream s) @inline => s.fns.write_fn || s.fns.write_byte_fn; +fn bool Stream.supports_flush(s) @inline => (bool)s.fns.flush_fn; +fn bool Stream.supports_seek(s) @inline => (bool)s.fns.seek_fn; +fn bool Stream.supports_available(s) @inline => s.fns.available_fn || s.fns.seek_fn; +fn bool Stream.supports_len(s) @inline => s.fns.len_fn || s.fns.seek_fn; +fn bool Stream.supports_read(s) @inline => s.fns.read_fn || s.fns.read_byte_fn; +fn bool Stream.supports_read_from(s) @inline => (bool)s.fns.read_stream_fn; +fn bool Stream.supports_write_to(s) @inline => (bool)s.fns.write_stream_fn; +fn bool Stream.supports_pushback_byte(s) @inline => s.fns.pushback_byte_fn || s.fns.seek_fn; +fn bool Stream.supports_write(s) @inline => s.fns.write_fn || s.fns.write_byte_fn; -fn void! Stream.destroy(Stream s) @inline @maydiscard +fn void! Stream.destroy(self) @inline @maydiscard { - if (s.fns.destroy_fn) return s.fns.destroy_fn(s); - return s.close(); + if (self.fns.destroy_fn) return self.fns.destroy_fn(self); + return self.close(); } -fn void! Stream.close(Stream s) @inline @maydiscard +fn void! Stream.close(self) @inline @maydiscard { - if (CloseStreamFn func = s.fns.close_fn) return func(s); + if (CloseStreamFn func = self.fns.close_fn) return func(self); } -fn usz! Stream.seek(Stream s, isz offset, Seek seek) @inline +fn usz! Stream.seek(self, isz offset, Seek seek) @inline { - if (SeekStreamFn func = s.fns.seek_fn) return func(s, offset, seek); + if (SeekStreamFn func = self.fns.seek_fn) return func(self, offset, seek); return IoError.NOT_SEEKABLE?; } -fn usz! Stream.available(Stream s) @inline +fn usz! Stream.available(self) @inline { - if (AvailableStreamFn func = s.fns.available_fn) return func(s); - if (SeekStreamFn func = s.fns.seek_fn) + if (AvailableStreamFn func = self.fns.available_fn) return func(self); + if (SeekStreamFn func = self.fns.seek_fn) { - usz curr = func(s, 0, Seek.CURSOR)!; - usz len = func(s, 0, Seek.END)!; - func(s, curr, Seek.SET)!; + usz curr = func(self, 0, Seek.CURSOR)!; + usz len = func(self, 0, Seek.END)!; + func(self, curr, Seek.SET)!; return len - curr; } return IoError.NOT_SEEKABLE?; } -fn usz! Stream.read(Stream s, char[] buffer) +fn usz! Stream.read(self, char[] buffer) { - if (ReadStreamFn func = s.fns.read_fn) return func(s, buffer); - if (ReadByteStreamFn func = s.fns.read_byte_fn) + if (ReadStreamFn func = self.fns.read_fn) return func(self, buffer); + if (ReadByteStreamFn func = self.fns.read_byte_fn) { usz len = 0; foreach (&cptr : buffer) { - char! c = func(s); + char! c = func(self); if (catch err = c) { case IoError.EOF: return len; @@ -98,18 +98,18 @@ fn usz! Stream.read(Stream s, char[] buffer) return IoError.UNSUPPORTED_OPERATION?; } -fn char! Stream.read_byte(Stream s) @inline +fn char! Stream.read_byte(self) @inline { - if (ReadByteStreamFn func = s.fns.read_byte_fn) return func(s); + if (ReadByteStreamFn func = self.fns.read_byte_fn) return func(self); return IoError.UNSUPPORTED_OPERATION?; } -fn String! Stream.readline(Stream s, Allocator* using = mem::heap()) +fn String! Stream.readline(self, Allocator* using = mem::heap()) { ReadByteStreamFn func; - if (func = s.fns.read_byte_fn, !func) return IoError.UNSUPPORTED_OPERATION?; + if (func = self.fns.read_byte_fn, !func) return IoError.UNSUPPORTED_OPERATION?; bool read = false; - char val = func(s)!; + char val = func(self)!; if (val == '\n') return ""; @stack_mem(256 + 64; Allocator* mem) { @@ -117,7 +117,7 @@ fn String! Stream.readline(Stream s, Allocator* using = mem::heap()) if (val != '\r') str.append(val); while (1) { - char! c = func(s); + char! c = func(self); if (catch err = c) { if (err == IoError.EOF) break; @@ -131,95 +131,95 @@ fn String! Stream.readline(Stream s, Allocator* using = mem::heap()) }; } -fn usz! Stream.write(Stream s, char[] bytes) @inline +fn usz! Stream.write(self, char[] bytes) @inline { - if (WriteStreamFn func = s.fns.write_fn) return func(s, bytes); - if (WriteByteStreamFn func = s.fns.write_byte_fn) + if (WriteStreamFn func = self.fns.write_fn) return func(self, bytes); + if (WriteByteStreamFn func = self.fns.write_byte_fn) { - foreach (c : bytes) func(s, c)!; + foreach (c : bytes) func(self, c)!; return bytes.len; } return IoError.UNSUPPORTED_OPERATION?; } -fn void! Stream.write_byte(Stream s, char b) @inline +fn void! Stream.write_byte(self, char b) @inline { - if (WriteByteStreamFn func = s.fns.write_byte_fn) return func(s, b); + if (WriteByteStreamFn func = self.fns.write_byte_fn) return func(self, b); return IoError.UNSUPPORTED_OPERATION?; } -fn usz! Stream.write_to(Stream s, Stream to) @inline +fn usz! Stream.write_to(self, Stream to) @inline { - if (WriteToStreamFn func = s.fns.write_stream_fn) return func(s, to); + if (WriteToStreamFn func = self.fns.write_stream_fn) return func(self, to); return IoError.UNSUPPORTED_OPERATION?; } -fn usz! Stream.read_from(Stream s, Stream from) @inline +fn usz! Stream.read_from(self, Stream from) @inline { - if (ReadFromStreamFn func = s.fns.read_stream_fn) return func(s, from); + if (ReadFromStreamFn func = self.fns.read_stream_fn) return func(self, from); return IoError.UNSUPPORTED_OPERATION?; } -fn void! Stream.flush(Stream s) @inline @maydiscard +fn void! Stream.flush(self) @inline @maydiscard { - if (FlushStreamFn func = s.fns.flush_fn) return func(s); + if (FlushStreamFn func = self.fns.flush_fn) return func(self); return IoError.UNSUPPORTED_OPERATION?; } -fn usz! Stream.len(Stream s) @inline +fn usz! Stream.len(self) @inline { - if (LenStreamFn func = s.fns.len_fn) return func(s); - if (SeekStreamFn func = s.fns.seek_fn) + if (LenStreamFn func = self.fns.len_fn) return func(self); + if (SeekStreamFn func = self.fns.seek_fn) { - usz curr = func(s, 0, Seek.CURSOR)!; - usz len = func(s, 0, Seek.END)!; - func(s, curr, Seek.SET)!; + usz curr = func(self, 0, Seek.CURSOR)!; + usz len = func(self, 0, Seek.END)!; + func(self, curr, Seek.SET)!; return len; } return IoError.NOT_SEEKABLE?; } -fn void! Stream.pushback_byte(Stream s) @inline +fn void! Stream.pushback_byte(self) @inline { - if (PushbackByteStreamFn func = s.fns.pushback_byte_fn) return func(s); - if (SeekStreamFn func = s.fns.seek_fn) + if (PushbackByteStreamFn func = self.fns.pushback_byte_fn) return func(self); + if (SeekStreamFn func = self.fns.seek_fn) { - func(s, -1, CURSOR)!; + func(self, -1, CURSOR)!; return; } return IoError.UNSUPPORTED_OPERATION?; } -fn void! Stream.write_string(Stream s, String str) @inline => (void)(s.write((char[])str)!); +fn void! Stream.write_string(self, String str) @inline => (void)(self.write((char[])str)!); -fn usz! Stream.copy_to(Stream s, Stream dst, char[] buffer = {}) +fn usz! Stream.copy_to(self, Stream dst, char[] buffer = {}) { - if (buffer.len) return copy_through_buffer(s, dst, buffer); - if (WriteToStreamFn func = s.fns.write_stream_fn) return func(s, dst); - if (ReadFromStreamFn func = dst.fns.read_stream_fn) return func(dst, s); + if (buffer.len) return copy_through_buffer(self, dst, buffer); + if (WriteToStreamFn func = self.fns.write_stream_fn) return func(self, dst); + if (ReadFromStreamFn func = dst.fns.read_stream_fn) return func(dst, self); $switch (env::MEMORY_ENV) $case NORMAL: @pool() { - return copy_through_buffer(s, dst, tmalloc(char, 4096)); + return copy_through_buffer(self, dst, tmalloc(char, 4096)); }; $case SMALL: @pool() { - return copy_through_buffer(s, dst, tmalloc(char, 1024)); + return copy_through_buffer(self, dst, tmalloc(char, 1024)); }; $case TINY: $case NONE: - return copy_through_buffer(s, dst, &&(char[256]{})); + return copy_through_buffer(self, dst, &&(char[256]{})); $endswitch } -macro usz! copy_through_buffer(Stream s, Stream dst, char[] buffer) @local +macro usz! copy_through_buffer(self, Stream dst, char[] buffer) @local { usz total_copied; while (true) { - usz! len = s.read(buffer); + usz! len = self.read(buffer); if (catch err = len) { case IoError.EOF: return total_copied; diff --git a/lib/std/io/stream/buffer.c3 b/lib/std/io/stream/buffer.c3 index ff27c8244..23f606fec 100644 --- a/lib/std/io/stream/buffer.c3 +++ b/lib/std/io/stream/buffer.c3 @@ -10,18 +10,18 @@ struct ReadBuffer /** * Buffer reads from a stream. - * @param [inout] b + * @param [inout] self * @require bytes.len > 0 - * @require b.bytes.len == 0 "Init may not run on already initialized data" + * @require self.bytes.len == 0 "Init may not run on already initialized data" **/ -fn void ReadBuffer.init(ReadBuffer *b, Stream stream, char[] bytes) +fn void ReadBuffer.init(&self, Stream stream, char[] bytes) { - *b = { .stream = stream, .bytes = bytes }; + *self = { .stream = stream, .bytes = bytes }; } -fn Stream ReadBuffer.as_stream(ReadBuffer *b) +fn Stream ReadBuffer.as_stream(&self) { - return { .fns = &readbuffer_interface, .data = b }; + return { .fns = &readbuffer_interface, .data = self }; } StreamInterface readbuffer_interface = { @@ -29,36 +29,41 @@ StreamInterface readbuffer_interface = { .read_byte_fn = fn(s) => ((ReadBuffer*)s.data).read_byte(), }; -fn usz! ReadBuffer.read(ReadBuffer *b, char[] bytes) +fn String ReadBuffer.as_str(&self) { - if (b.read_idx == b.write_idx) + return (String)self.bytes[self.read_idx:self.write_idx - self.read_idx]; +} + +fn usz! ReadBuffer.read(&self, char[] bytes) +{ + if (self.read_idx == self.write_idx) { - if (b.read_idx == 0 && bytes.len >= b.bytes.len) + if (self.read_idx == 0 && bytes.len >= self.bytes.len) { // Read directly into the input buffer. - return b.stream.read(bytes)!; + return self.stream.read(bytes)!; } - b.refill()!; + self.refill()!; } - usz n = min(b.write_idx - b.read_idx, bytes.len); - bytes[:n] = b.bytes[b.read_idx:n]; - b.read_idx += n; + usz n = min(self.write_idx - self.read_idx, bytes.len); + bytes[:n] = self.bytes[self.read_idx:n]; + self.read_idx += n; return n; } -fn char! ReadBuffer.read_byte(ReadBuffer *b) +fn char! ReadBuffer.read_byte(&self) { - if (b.read_idx == b.write_idx) b.refill()!; - if (b.read_idx == b.write_idx) return IoError.EOF?; - char c = b.bytes[b.read_idx]; - b.read_idx++; + if (self.read_idx == self.write_idx) self.refill()!; + if (self.read_idx == self.write_idx) return IoError.EOF?; + char c = self.bytes[self.read_idx]; + self.read_idx++; return c; } -fn void! ReadBuffer.refill(ReadBuffer* b) @local +fn void! ReadBuffer.refill(&self) @local { - b.read_idx = 0; - b.write_idx = b.stream.read(b.bytes)!; + self.read_idx = 0; + self.write_idx = self.stream.read(self.bytes)!; } struct WriteBuffer @@ -70,18 +75,18 @@ struct WriteBuffer /** * Buffer writes to a stream. Call `flush` when done writing to the buffer. - * @param [inout] b + * @param [inout] self * @require bytes.len > 0 "Non-empty buffer required" - * @require b.bytes.len == 0 "Init may not run on already initialized data" + * @require self.bytes.len == 0 "Init may not run on already initialized data" **/ -fn void WriteBuffer.init(WriteBuffer *b, Stream stream, char[] bytes) +fn void WriteBuffer.init(&self, Stream stream, char[] bytes) { - *b = { .stream = stream, .bytes = bytes }; + *self = { .stream = stream, .bytes = bytes }; } -fn Stream WriteBuffer.as_stream(WriteBuffer *b) +fn Stream WriteBuffer.as_stream(&self) { - return { .fns = &writebuffer_interface, .data = b }; + return { .fns = &writebuffer_interface, .data = self }; } StreamInterface writebuffer_interface = { @@ -90,49 +95,49 @@ StreamInterface writebuffer_interface = { .write_byte_fn = fn(s, char c) => ((WriteBuffer*)s.data).write_byte(c), }; -fn String WriteBuffer.as_str(WriteBuffer* b) +fn String WriteBuffer.as_str(&self) { - return (String)b.bytes[:b.index]; + return (String)self.bytes[:self.index]; } -fn void! WriteBuffer.flush(WriteBuffer* b) +fn void! WriteBuffer.flush(&self) { - b.write_pending()!; - if (b.stream.supports_flush()) b.stream.flush()!; + self.write_pending()!; + if (self.stream.supports_flush()) self.stream.flush()!; } -fn usz! WriteBuffer.write(WriteBuffer* b, char[] bytes) +fn usz! WriteBuffer.write(&self, char[] bytes) { - usz n = b.bytes.len - b.index; + usz n = self.bytes.len - self.index; if (bytes.len < n) { // Enough room in the buffer. - b.bytes[b.index:bytes.len] = bytes[..]; - b.index += bytes.len; + self.bytes[self.index:bytes.len] = bytes[..]; + self.index += bytes.len; return bytes.len; } - b.write_pending()!; - if (bytes.len >= b.bytes.len) + self.write_pending()!; + if (bytes.len >= self.bytes.len) { // Write directly to the stream. - return b.stream.write(bytes); + return self.stream.write(bytes); } // Buffer the data. - b.bytes[:bytes.len] = bytes[..]; - b.index = bytes.len; + self.bytes[:bytes.len] = bytes[..]; + self.index = bytes.len; return bytes.len; } -fn void! WriteBuffer.write_byte(WriteBuffer* b, char c) +fn void! WriteBuffer.write_byte(&self, char c) { - usz n = b.bytes.len - b.index; - if (n == 0) b.write_pending()!; - b.bytes[0] = c; - b.index = 1; + usz n = self.bytes.len - self.index; + if (n == 0) self.write_pending()!; + self.bytes[0] = c; + self.index = 1; } -fn void! WriteBuffer.write_pending(WriteBuffer* b) @local +fn void! WriteBuffer.write_pending(&self) @local { - b.index -= b.stream.write(b.bytes[:b.index])!; - if (b.index != 0) return IoError.INCOMPLETE_WRITE?; + self.index -= self.stream.write(self.bytes[:self.index])!; + if (self.index != 0) return IoError.INCOMPLETE_WRITE?; } \ No newline at end of file diff --git a/lib/std/io/stream/bytereader.c3 b/lib/std/io/stream/bytereader.c3 index dc819ab6c..6afd64e8b 100644 --- a/lib/std/io/stream/bytereader.c3 +++ b/lib/std/io/stream/bytereader.c3 @@ -7,64 +7,64 @@ struct ByteReader usz index; } -fn void ByteReader.init(ByteReader* reader, char[] bytes) +fn void ByteReader.init(&self, char[] bytes) { - *reader = { .bytes = bytes }; + *self = { .bytes = bytes }; } -fn Stream ByteReader.as_stream(ByteReader* reader) +fn Stream ByteReader.as_stream(&self) { - return { .fns = &bytereader_interface, .data = reader }; + return { .fns = &bytereader_interface, .data = self }; } -fn usz! ByteReader.read(ByteReader* reader, char[] bytes) +fn usz! ByteReader.read(&self, char[] bytes) { - if (reader.index >= reader.bytes.len) return IoError.EOF?; - usz len = math::min(reader.bytes.len - reader.index, bytes.len); + if (self.index >= self.bytes.len) return IoError.EOF?; + usz len = math::min(self.bytes.len - self.index, bytes.len); if (len == 0) return 0; - mem::copy(bytes.ptr, &reader.bytes[reader.index], len); - reader.index += len; + mem::copy(bytes.ptr, &self.bytes[self.index], len); + self.index += len; return len; } -fn char! ByteReader.read_byte(ByteReader* reader) +fn char! ByteReader.read_byte(&self) { - if (reader.index >= reader.bytes.len) return IoError.EOF?; - return reader.bytes[reader.index++]; + if (self.index >= self.bytes.len) return IoError.EOF?; + return self.bytes[self.index++]; } -fn void! ByteReader.pushback_byte(ByteReader* reader) +fn void! ByteReader.pushback_byte(&self) { - if (!reader.index) return IoError.INVALID_PUSHBACK?; - reader.index--; + if (!self.index) return IoError.INVALID_PUSHBACK?; + self.index--; } -fn usz! ByteReader.seek(ByteReader* reader, isz offset, Seek seek) +fn usz! ByteReader.seek(&self, isz offset, Seek seek) { isz new_index; switch (seek) { case SET: new_index = offset; - case CURSOR: new_index = reader.index + offset; - case END: new_index = reader.bytes.len + offset; + case CURSOR: new_index = self.index + offset; + case END: new_index = self.bytes.len + offset; } if (new_index < 0) return IoError.INVALID_POSITION?; - reader.index = new_index; + self.index = new_index; return new_index; } -fn usz! ByteReader.write_stream(ByteReader* reader, Stream writer) +fn usz! ByteReader.write_stream(&self, Stream writer) { - if (reader.index >= reader.bytes.len) return 0; - usz written = writer.write(reader.bytes[reader.index..])!; - reader.index += written; - assert(reader.index <= reader.bytes.len); + if (self.index >= self.bytes.len) return 0; + usz written = writer.write(self.bytes[self.index..])!; + self.index += written; + assert(self.index <= self.bytes.len); return written; } -fn usz ByteReader.available(ByteReader* reader) +fn usz ByteReader.available(&self) { - return math::max((isz)0, (isz)reader.bytes.len - reader.index); + return math::max((isz)0, (isz)self.bytes.len - self.index); } StreamInterface bytereader_interface = { diff --git a/lib/std/io/stream/bytewriter.c3 b/lib/std/io/stream/bytewriter.c3 index d3f069c50..def706707 100644 --- a/lib/std/io/stream/bytewriter.c3 +++ b/lib/std/io/stream/bytewriter.c3 @@ -8,107 +8,107 @@ struct ByteWriter } /** - * @param [&inout] writer + * @param [&inout] self * @param [&in] using - * @require writer.bytes.len == 0 "Init may not run on on already initialized data" + * @require self.bytes.len == 0 "Init may not run on on already initialized data" * @ensure using != null, index == 0 **/ -fn void ByteWriter.init(ByteWriter* writer, Allocator* using = mem::heap()) +fn void ByteWriter.init(&self, Allocator* using = mem::heap()) { - *writer = { .bytes = {}, .allocator = using }; + *self = { .bytes = {}, .allocator = using }; } -fn void ByteWriter.init_buffer(ByteWriter* writer, char[] data) +fn void ByteWriter.init_buffer(&self, char[] data) { - *writer = { .bytes = data, .allocator = null }; + *self = { .bytes = data, .allocator = null }; } /** - * @param [&inout] writer - * @require writer.bytes.len == 0 "Init may not run on on already initialized data" + * @param [&inout] self + * @require self.bytes.len == 0 "Init may not run on on already initialized data" **/ -fn void ByteWriter.tinit(ByteWriter* writer) +fn void ByteWriter.tinit(&self) { - *writer = { .bytes = {}, .allocator = mem::temp() }; + *self = { .bytes = {}, .allocator = mem::temp() }; } -fn Stream ByteWriter.as_stream(ByteWriter* writer) +fn Stream ByteWriter.as_stream(&self) { - return { .fns = &bytewriter_interface, .data = writer }; + return { .fns = &bytewriter_interface, .data = self }; } -fn void ByteWriter.destroy(ByteWriter* writer) +fn void ByteWriter.destroy(&self) { - if (!writer.allocator) return; - if (void* ptr = writer.bytes.ptr) free(ptr, .using = writer.allocator); - *writer = { }; + if (!self.allocator) return; + if (void* ptr = self.bytes.ptr) free(ptr, .using = self.allocator); + *self = { }; } -fn String ByteWriter.as_str(ByteWriter* writer) +fn String ByteWriter.as_str(&self) { - return (String)writer.bytes[:writer.index]; + return (String)self.bytes[:self.index]; } -fn void! ByteWriter.ensure_capacity(ByteWriter* writer, usz len) @inline +fn void! ByteWriter.ensure_capacity(&self, usz len) @inline { - if (writer.bytes.len > len) return; - if (!writer.allocator) return IoError.OUT_OF_SPACE?; + if (self.bytes.len > len) return; + if (!self.allocator) return IoError.OUT_OF_SPACE?; if (len < 16) len = 16; usz new_capacity = math::next_power_of_2(len); - char* new_ptr = realloc_checked(writer.bytes.ptr, new_capacity, .using = writer.allocator)!; - writer.bytes = new_ptr[:new_capacity]; + char* new_ptr = realloc_checked(self.bytes.ptr, new_capacity, .using = self.allocator)!; + self.bytes = new_ptr[:new_capacity]; } -fn usz! ByteWriter.write(ByteWriter* writer, char[] bytes) +fn usz! ByteWriter.write(&self, char[] bytes) { - writer.ensure_capacity(writer.index + bytes.len)!; - mem::copy(&writer.bytes[writer.index], bytes.ptr, bytes.len); - writer.index += bytes.len; + self.ensure_capacity(self.index + bytes.len)!; + mem::copy(&self.bytes[self.index], bytes.ptr, bytes.len); + self.index += bytes.len; return bytes.len; } -fn void! ByteWriter.write_byte(ByteWriter* writer, char c) +fn void! ByteWriter.write_byte(&self, char c) { - writer.ensure_capacity(writer.index + 1)!; - writer.bytes[writer.index++] = c; + self.ensure_capacity(self.index + 1)!; + self.bytes[self.index++] = c; } /** - * @param [&inout] writer + * @param [&inout] self * @param reader **/ -fn usz! ByteWriter.read_from(ByteWriter* writer, Stream reader) +fn usz! ByteWriter.read_from(&self, Stream reader) { - usz start_index = writer.index; + usz start_index = self.index; if (reader.supports_available()) { while (usz available = reader.available()!) { - writer.ensure_capacity(writer.index + available)!; - usz read = reader.read(writer.bytes[writer.index..])!; - writer.index += read; + self.ensure_capacity(self.index + available)!; + usz read = reader.read(self.bytes[self.index..])!; + self.index += read; } - return writer.index - start_index; + return self.index - start_index; } - if (writer.bytes.len == 0) + if (self.bytes.len == 0) { - writer.ensure_capacity(16)!; + self.ensure_capacity(16)!; } while (true) { // See how much we can read. - usz len_to_read = writer.bytes.len - writer.index; + usz len_to_read = self.bytes.len - self.index; // Less than 16 bytes? Double the capacity if (len_to_read < 16) { - writer.ensure_capacity(writer.bytes.len * 2)!; - len_to_read = writer.bytes.len - writer.index; + self.ensure_capacity(self.bytes.len * 2)!; + len_to_read = self.bytes.len - self.index; } // Read into the rest of the buffer - usz read = reader.read(writer.bytes[writer.index..])!; - writer.index += read; + usz read = reader.read(self.bytes[self.index..])!; + self.index += read; // Ok, we reached the end. - if (read < len_to_read) return writer.index - start_index; + if (read < len_to_read) return self.index - start_index; // Otherwise go another round } } diff --git a/lib/std/io/stream/dstringwriter.c3 b/lib/std/io/stream/dstringwriter.c3 index 85006aec0..e163914f3 100644 --- a/lib/std/io/stream/dstringwriter.c3 +++ b/lib/std/io/stream/dstringwriter.c3 @@ -1,8 +1,8 @@ module std::io; -fn Stream DString.as_stream(DString* dstring) +fn Stream DString.as_stream(&self) { - return { .fns = &dstring_interface, .data = dstring }; + return { .fns = &dstring_interface, .data = self }; } StreamInterface dstring_interface = { diff --git a/lib/std/io/stream/filestream.c3 b/lib/std/io/stream/filestream.c3 index d9348eb5a..f938fb533 100644 --- a/lib/std/io/stream/filestream.c3 +++ b/lib/std/io/stream/filestream.c3 @@ -1,8 +1,8 @@ module std::io; -fn Stream File.as_stream(File* file) +fn Stream File.as_stream(&self) { - return { .fns = &filestream_interface, .data = file }; + return { .fns = &filestream_interface, .data = self }; } StreamInterface filestream_interface = { diff --git a/test/unit/stdlib/collections/list.c3 b/test/unit/stdlib/collections/list.c3 index c863718c2..1c6ceb74e 100644 --- a/test/unit/stdlib/collections/list.c3 +++ b/test/unit/stdlib/collections/list.c3 @@ -16,7 +16,9 @@ fn void! test_delete_contains_index() test.push(3); assert(test.array_view() == int[]{ 1, 2, 3 }); assert(test.contains(3)); - test.remove(1); + test[0] = 10; + assert(test.contains(10)); + test.remove(10); assert(test.array_view() == int[]{ 2, 3 }); assert(!test.contains(1)); assert(test.contains(2));