- Warn on use of visibility modifiers on methods. #2962

This commit is contained in:
Christoffer Lerno
2026-02-21 21:10:08 +01:00
parent e1ec4b1235
commit dc52478c09
49 changed files with 907 additions and 890 deletions

View File

@@ -91,16 +91,7 @@ fn void Formatter.init(&self, OutputFn out_fn, void* data = null)
*self = { .data = data, .out_fn = out_fn};
}
fn usz? Formatter.out(&self, char c) @private
{
if (catch err = self.out_fn(self.data, c))
{
if (self.first_fault) return self.first_fault~;
self.first_fault = err;
return err~;
}
return 1;
}
fn usz? Formatter.print_with_function(&self, Printable arg)
{
@@ -115,7 +106,7 @@ fn usz? Formatter.print_with_function(&self, Printable arg)
self.width = old_width;
self.prec = old_prec;
}
if (!arg) return self.out_substr("(null)");
if (!arg) return formatter_out_substr(self, "(null)");
return arg.to_format(self);
}
if (&arg.to_constant_string)
@@ -129,161 +120,12 @@ fn usz? Formatter.print_with_function(&self, Printable arg)
self.width = old_width;
self.prec = old_prec;
}
if (!arg) return self.out_substr("(null)");
return self.out_substr(arg.to_constant_string());
if (!arg) return formatter_out_substr(self, "(null)");
return formatter_out_substr(self, arg.to_constant_string());
}
return NOT_FOUND~;
}
fn usz? Formatter.out_unknown(&self, String category, any arg) @private
{
return self.out_substr("<") + self.out_substr(category) + self.out_substr(" type:") + self.ntoa((iptr)arg.type, false, 16) + self.out_substr(", addr:") + self.ntoa((iptr)arg.ptr, false, 16) + self.out_substr(">");
}
fn usz? Formatter.out_collection(&self, any arg, String open, String close) @private
{
typeid inner = arg.type.inner;
if (inner == void.typeid) inner = char.typeid;
usz size = inner.sizeof;
usz alen;
void* data_ptr;
if (arg.type.kindof == SLICE)
{
String* temp = arg.ptr;
data_ptr = temp.ptr;
alen = temp.len;
}
else
{
data_ptr = arg.ptr;
alen = arg.type.len;
}
PrintFlags flags = self.flags;
uint width = self.width;
defer
{
self.flags = flags;
self.width = width;
}
self.flags = {};
self.width = 0;
usz len = self.out_substr(open)!;
for (usz i = 0; i < alen; i++)
{
if (i != 0) len += self.out_substr(", ")!;
len += self.out_str(any_make(data_ptr, inner))!;
data_ptr += size;
}
len += self.out_substr(close)!;
return len;
}
fn usz? Formatter.out_str(&self, any arg) @private
{
switch (arg.type.kindof)
{
case VOID:
return self.out_substr("void");
case FAULT:
fault f = *(fault*)arg.ptr;
return self.out_substr(f ? f.nameof : "(empty-fault)");
case INTERFACE:
any a = *(any*)arg;
return a ? self.out_str(a) : self.out_substr("(empty-interface)");
case ANY:
any a = *(any*)arg;
return a ? self.out_str(a) : self.out_substr("(empty-any)");
case OPTIONAL:
unreachable();
case SIGNED_INT:
case UNSIGNED_INT:
case FLOAT:
case FUNC:
case POINTER:
PrintFlags flags = self.flags;
uint width = self.width;
defer
{
self.flags = flags;
self.width = width;
}
self.flags = {};
self.width = 0;
switch (arg.type.kindof)
{
case SIGNED_INT:
case UNSIGNED_INT:
return self.ntoa_any(arg, 10) ?? self.out_substr("<INVALID>");
case FLOAT:
return self.ftoa(float_from_any(arg)) ?? self.out_substr("ERR");
case FUNC:
case POINTER:
if (arg.type.kindof == POINTER && arg.type.inner != void.typeid)
{
void** pointer = arg.ptr;
any deref = any_make(*pointer, arg.type.inner);
usz? n = self.print_with_function((Printable)deref);
if (try n) return n;
if (@catch(n) != NOT_FOUND) n!;
}
return self.out_substr("0x")! + self.ntoa_any(arg, 16);
default:
unreachable();
}
case BOOL:
return self.out_substr(*(bool*)arg.ptr ? "true" : "false");
default:
}
usz? n = self.print_with_function((Printable)arg);
if (try n) return n;
if (@catch(n) != NOT_FOUND) n!;
switch (arg.type.kindof)
{
case TYPEID:
return self.out_substr("typeid[")! + self.ntoa((iptr)*(typeid*)arg, false, 16)! + self.out_substr("]")!;
case ENUM:
usz i = types::any_to_enum_ordinal(arg, usz)!!;
assert(i < arg.type.names.len, "Illegal enum value found, numerical value was %d.", i);
return self.out_substr(arg.type.names[i]);
case STRUCT:
return self.out_unknown("struct", arg);
case UNION:
return self.out_unknown("union", arg);
case BITSTRUCT:
return self.out_unknown("bitstruct", arg);
case CONST_ENUM:
case DISTINCT:
if (arg.type == String.typeid)
{
return self.out_substr(*(String*)arg);
}
if (arg.type == ZString.typeid)
{
return self.out_substr(*(ZString*)arg ? ((ZString*)arg).str_view() : "(null)");
}
if (arg.type == DString.typeid)
{
return self.out_substr(*(DString*)arg ? ((DString*)arg).str_view() : "(null)");
}
return self.out_str(arg.as_inner());
case ARRAY:
return self.out_collection(arg, "[", "]");
case VECTOR:
return self.out_collection(arg, "[<", ">]");
case SLICE:
return self.out_collection(arg, "[", "]");
case ANY:
case INTERFACE:
unreachable("Already handled");
default:
}
return self.out_substr("Invalid type");
}
fn void? out_null_fn(void* data @unused, char c @unused) @private
{
@@ -291,7 +133,7 @@ fn void? out_null_fn(void* data @unused, char c @unused) @private
macro usz? @report_fault(Formatter* f, $fault)
{
(void)f.out_substr($fault);
(void)formatter_out_substr(f, $fault);
return INVALID_FORMAT~;
}
@@ -307,69 +149,14 @@ macro usz? @wrap_bad(Formatter* f, #action)
return f.first_err(err)~;
default:
err = f.first_err(INVALID_ARGUMENT);
f.out_substr("<INVALID>")!;
formatter_out_substr(f, "<INVALID>")!;
return err~;
}
}
return len;
}
fn usz? Formatter.out_hex_buffer(&self, any arg) @private @inline
{
char[] out @noinit;
switch (arg.type)
{
case char[]:
case ichar[]:
out = *(char[]*)arg;
default:
if (arg.type.kindof == ARRAY && (arg.type.inner == char.typeid || arg.type.inner == ichar.typeid))
{
out = ((char*)arg.ptr)[:arg.type.sizeof];
break;
}
if (arg.type.kindof == POINTER)
{
// Maybe there is a more idiomatic way here
out = ((*(char**)arg.ptr))[:arg.type.inner.sizeof];
break;
}
return self.out_substr("<INVALID>");
}
usz len = out.len * 2;
usz total;
if (self.flags.left)
{
total += print_hex_chars(self, out, self.flags.uppercase)!;
total += self.pad(' ', self.width, (isz)total)!;
}
else
{
if (self.width) total += self.pad(' ', self.width, (isz)len)!;
total += print_hex_chars(self, out, self.flags.uppercase)!;
}
return total;
}
fn usz? Formatter.out_str_pad(&self, any arg) @private @inline
{
usz total;
if (self.width && !self.flags.left)
{
OutputFn out_fn = self.out_fn;
self.out_fn = (OutputFn)&out_null_fn;
usz len = self.out_str(arg)!;
self.out_fn = out_fn;
total += self.pad(' ', self.width, (isz)len)!;
}
usz len = self.out_str(arg)!;
total += len;
if (self.flags.left)
{
total += self.pad(' ', self.width, (isz)len)!;
}
return total;
}
fn usz? Formatter.vprintf(&self, String format, any[] anys)
{
@@ -389,7 +176,7 @@ fn usz? Formatter.vprintf(&self, String format, any[] anys)
if (c != '%')
{
// no
total_len += self.out(c)!;
total_len += self.print_char(c)!;
continue;
}
i++;
@@ -397,7 +184,7 @@ fn usz? Formatter.vprintf(&self, String format, any[] anys)
c = format[i];
if (c == '%')
{
total_len += self.out(c)!;
total_len += self.print_char(c)!;
continue;
}
// evaluate flags
@@ -443,7 +230,7 @@ fn usz? Formatter.vprintf(&self, String format, any[] anys)
if (variant_index >= anys.len)
{
self.first_err(NOT_ENOUGH_ARGUMENTS);
total_len += self.out_substr("<MISSING>")!;
total_len += formatter_out_substr(self, "<MISSING>")!;
continue;
}
any current = anys[variant_index++];
@@ -471,37 +258,37 @@ fn usz? Formatter.vprintf(&self, String format, any[] anys)
self.flags.uppercase = true;
nextcase;
case 'a':
total_len += @wrap_bad(self, self.atoa(float_from_any(current)))!;
total_len += @wrap_bad(self, formatter_atoa(self, float_from_any(current)))!;
continue;
case 'F' :
self.flags.uppercase = true;
nextcase;
case 'f':
total_len += @wrap_bad(self, self.ftoa(float_from_any(current)))!;
total_len += @wrap_bad(self, formatter_ftoa(self, float_from_any(current)))!;
continue;
case 'E':
self.flags.uppercase = true;
nextcase;
case 'e':
total_len += @wrap_bad(self, self.etoa(float_from_any(current)))!;
total_len += @wrap_bad(self, formatter_etoa(self, float_from_any(current)))!;
continue;
case 'G':
self.flags.uppercase = true;
nextcase;
case 'g':
total_len += @wrap_bad(self, self.gtoa(float_from_any(current)))!;
total_len += @wrap_bad(self, formatter_gtoa(self, float_from_any(current)))!;
continue;
case 'c':
total_len += self.out_char(current)!;
total_len += formatter_out_char(self, current)!;
continue;
case 'H':
self.flags.uppercase = true;
nextcase;
case 'h':
total_len += self.out_hex_buffer(current)!;
total_len += formatter_out_hex_buffer(self, current)!;
continue;
case 's':
total_len += self.out_str_pad(current)!;
total_len += formatter_out_str_pad(self, current)!;
continue;
case 'p':
self.flags.zeropad = true;
@@ -509,7 +296,7 @@ fn usz? Formatter.vprintf(&self, String format, any[] anys)
base = 16;
default:
self.first_err(INVALID_FORMAT);
total_len += self.out_substr("<BAD FORMAT>")!;
total_len += formatter_out_substr(self, "<BAD FORMAT>")!;
continue;
}
if (base != 10)
@@ -521,13 +308,25 @@ fn usz? Formatter.vprintf(&self, String format, any[] anys)
if (self.flags.precision) self.flags.zeropad = false;
bool is_neg;
total_len += @wrap_bad(self, self.ntoa(int_from_any(current, &is_neg), is_neg, base))!;
total_len += @wrap_bad(self, formatter_ntoa(self, int_from_any(current, &is_neg), is_neg, base))!;
}
if (self.first_fault) return self.first_fault~;
return total_len;
}
fn usz? Formatter.out(&self, char c) @deprecated("Use print_char") => self.print_char(c);
fn usz? Formatter.print_char(&self, char c)
{
if (catch err = self.out_fn(self.data, c))
{
if (self.first_fault) return self.first_fault~;
self.first_fault = err;
return err~;
}
return 1;
}
fn usz? Formatter.print(&self, String str)
{
@@ -536,6 +335,6 @@ fn usz? Formatter.print(&self, String str)
// use null output function
self.out_fn = &out_null_fn;
}
foreach (c : str) self.out(c)!;
foreach (c : str) self.print_char(c)!;
return str.len;
}

View File

@@ -13,10 +13,10 @@ fn usz? print_hex_chars(Formatter* f, char[] out, bool uppercase) @inline
foreach (c : out)
{
char digit = c >> 4;
f.out(digit + (digit < 10 ? '0' : past_10))!;
f.print_char(digit + (digit < 10 ? '0' : past_10))!;
len++;
digit = c & 0xf;
f.out(digit + (digit < 10 ? '0' : past_10))!;
f.print_char(digit + (digit < 10 ? '0' : past_10))!;
len++;
}
return len;
@@ -29,10 +29,10 @@ macro fault Formatter.first_err(&self, fault f)
return f;
}
fn usz? Formatter.adjust(&self, usz len) @local
fn usz? formatter_adjust(Formatter* f, usz len) @local
{
if (!self.flags.left) return 0;
return self.pad(' ', self.width, len);
if (!f.flags.left) return 0;
return formatter_pad(f, ' ', f.width, len);
}
fn uint128? int_from_any(any arg, bool *is_neg) @private
@@ -156,11 +156,11 @@ fn uint simple_atoi(char* buf, usz maxlen, usz* len_ptr) @inline @private
return i;
}
fn usz? Formatter.out_substr(&self, String str) @private
fn usz? formatter_out_substr(Formatter* f, String str) @private
{
usz l = conv::utf8_codepoints(str);
uint prec = self.prec;
if (self.flags.precision && l < prec) l = prec;
uint prec = f.prec;
if (f.flags.precision && l < prec) l = prec;
usz index = 0;
usz chars = str.len;
char* ptr = str.ptr;
@@ -168,17 +168,17 @@ fn usz? Formatter.out_substr(&self, String str) @private
{
char c = ptr[index];
// Break if we have precision set and we ran out...
if (c & 0xC0 != 0x80 && self.flags.precision && !prec--) break;
self.out(c)!;
if (c & 0xC0 != 0x80 && f.flags.precision && !prec--) break;
f.print_char(c)!;
index++;
}
return index;
}
fn usz? Formatter.pad(&self, char c, isz width, isz len) @inline
fn usz? formatter_pad(Formatter* f, char c, isz width, isz len) @inline
{
isz delta = width - len;
for (isz i = 0; i < delta; i++) self.out(c)!;
for (isz i = 0; i < delta; i++) f.print_char(c)!;
return max(0, delta);
}
@@ -191,7 +191,7 @@ fn char* fmt_u(uint128 x, char* s)
fn usz? Formatter.out_chars(&self, char[] s)
{
foreach (c : s) self.out(c)!;
foreach (c : s) self.print_char(c)!;
return s.len;
}
@@ -203,12 +203,12 @@ enum FloatFormatting
HEX
}
fn usz? Formatter.etoa(&self, double y) => self.floatformat(EXPONENTIAL, y);
fn usz? Formatter.ftoa(&self, double y) => self.floatformat(FLOAT, y);
fn usz? Formatter.gtoa(&self, double y) => self.floatformat(ADAPTIVE, y);
fn usz? Formatter.atoa(&self, double y) => self.floatformat(HEX, y);
fn usz? formatter_etoa(Formatter* self, double y) => formatter_floatformat(self, EXPONENTIAL, y);
fn usz? formatter_ftoa(Formatter* self, double y) => formatter_floatformat(self, FLOAT, y);
fn usz? formatter_gtoa(Formatter* self, double y) => formatter_floatformat(self, ADAPTIVE, y);
fn usz? formatter_atoa(Formatter* self, double y) => formatter_floatformat(self, HEX, y);
fn usz? Formatter.floatformat_hex(&self, double y, bool is_neg, isz pl, isz p) @private @inline
fn usz? formatter_floatformat_hex(Formatter* self, double y, bool is_neg, isz pl, isz p) @private @inline
{
double round = 8.0;
// 0x / 0X
@@ -261,18 +261,18 @@ fn usz? Formatter.floatformat_hex(&self, double y, bool is_neg, isz pl, isz p) @
usz l = (usz)(p && outlen - 2 < p
? p + 2 + explen
: outlen + explen);
if (!self.flags.left && !self.flags.zeropad) len += self.pad(' ', self.width, pl + l)!;
if (is_neg || self.flags.plus) len += self.out(is_neg ? '-' : '+')!;
if (!self.flags.left && !self.flags.zeropad) len += formatter_pad(self, ' ', self.width, pl + l)!;
if (is_neg || self.flags.plus) len += self.print_char(is_neg ? '-' : '+')!;
len += self.out_chars(self.flags.uppercase ? "0X" : "0x")!;
if (self.flags.zeropad) len += self.pad('0', self.width, pl + l)!;
if (self.flags.zeropad) len += formatter_pad(self, '0', self.width, pl + l)!;
len += self.out_chars(buf[:outlen])!;
len += self.pad('0', (isz)l - outlen - explen, 0)!;
len += formatter_pad(self, '0', (isz)l - outlen - explen, 0)!;
len += self.out_chars(estr[:explen])!;
if (self.flags.left) len += self.pad(' ', self.width, pl + (isz)l)!;
if (self.flags.left) len += formatter_pad(self, ' ', self.width, pl + (isz)l)!;
return len;
}
fn usz? Formatter.floatformat(&self, FloatFormatting formatting, double y) @private
fn usz? formatter_floatformat(Formatter* 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
@@ -290,17 +290,17 @@ fn usz? Formatter.floatformat(&self, FloatFormatting formatting, double y) @priv
{
usz len;
// Add padding
if (!self.flags.left) len += self.pad(' ', self.width, 3 + pl)!;
if (!self.flags.left) len += formatter_pad(self, ' ', self.width, 3 + pl)!;
String s = self.flags.uppercase ? "INF" : "inf";
if (math::is_nan(y)) s = self.flags.uppercase ? "NAN" : "nan";
if (pl) len += self.out(is_neg ? '-' : '+')!;
if (pl) len += self.print_char(is_neg ? '-' : '+')!;
len += self.out_chars(s)!;
if (self.flags.left) len += self.pad(' ', self.width, 3 + pl)!;
if (self.flags.left) len += formatter_pad(self, ' ', self.width, 3 + pl)!;
return len;
}
isz p = self.flags.precision ? self.prec : -1;
if (formatting == HEX) return self.floatformat_hex(y, is_neg, pl, p);
if (formatting == HEX) return formatter_floatformat_hex(self, y, is_neg, pl, p);
// Rescale
int e2;
@@ -483,9 +483,9 @@ fn usz? Formatter.floatformat(&self, FloatFormatting formatting, double y) @priv
}
if (l > int.max - pl) return INTERNAL_BUFFER_EXCEEDED~;
usz len;
if (!self.flags.left && !self.flags.zeropad) len += self.pad(' ', self.width, pl + l)!;
if (is_neg || self.flags.plus) len += self.out(is_neg ? '-' : '+')!;
if (self.flags.zeropad) len += self.pad('0', self.width, pl + l)!;
if (!self.flags.left && !self.flags.zeropad) len += formatter_pad(self, ' ', self.width, pl + l)!;
if (is_neg || self.flags.plus) len += self.print_char(is_neg ? '-' : '+')!;
if (self.flags.zeropad) len += formatter_pad(self, '0', self.width, pl + l)!;
char[9] buf_array;
char* buf = &buf_array[0];
@@ -506,14 +506,14 @@ fn usz? Formatter.floatformat(&self, FloatFormatting formatting, double y) @priv
}
len += self.out_chars(s[:buf + 9 - s])!;
}
if (p || self.flags.hash) len += self.out('.')!;
if (p || self.flags.hash) len += self.print_char('.')!;
for (; d < z && p > 0; d++, p -= 9)
{
char* s = fmt_u(*d, buf + 9);
while (s > buf) *--s = '0';
len += self.out_chars(s[:math::min((isz)9, p)])!;
}
len += self.pad('0', p + 9, 9)!;
len += formatter_pad(self, '0', p + 9, 9)!;
}
else
{
@@ -528,21 +528,42 @@ fn usz? Formatter.floatformat(&self, FloatFormatting formatting, double y) @priv
}
else
{
len += self.out(s++[0])!;
if (p > 0 || self.flags.hash) len += self.out('.')!;
len += self.print_char(s++[0])!;
if (p > 0 || self.flags.hash) len += self.print_char('.')!;
}
len += self.out_chars(s[:math::min(buf + 9 - s, p)])!;
p -= buf + 9 - s;
}
len += self.pad('0', p + 18, 18)!;
len += formatter_pad(self, '0', p + 18, 18)!;
len += self.out_chars(estr[:ebuf - estr])!;
}
if (self.flags.left) len += self.pad(' ', self.width, pl + l)!;
if (self.flags.left) len += formatter_pad(self, ' ', self.width, pl + l)!;
return len;
}
fn usz? formatter_out_str_pad(Formatter* self, any arg) @private @inline
{
usz total;
if (self.width && !self.flags.left)
{
OutputFn out_fn = self.out_fn;
self.out_fn = (OutputFn)&out_null_fn;
usz len = formatter_out_str(self, arg)!;
self.out_fn = out_fn;
total += formatter_pad(self, ' ', self.width, (isz)len)!;
}
usz len = formatter_out_str(self, arg)!;
total += len;
if (self.flags.left)
{
total += formatter_pad(self, ' ', self.width, (isz)len)!;
}
return total;
}
const char[201] DIGIT_PAIRS @private =
"00102030405060708090"
"01112131415161718191"
@@ -555,18 +576,18 @@ const char[201] DIGIT_PAIRS @private =
"08182838485868788898"
"09192939495969798999";
fn usz? Formatter.ntoa(&self, uint128 value, bool negative, uint base) @private
fn usz? formatter_ntoa(Formatter* f, uint128 value, bool negative, uint base) @private
{
char[PRINTF_NTOA_BUFFER_SIZE] buf @noinit;
usz len;
// no hash for 0 values
if (!value) self.flags.hash = false;
if (!value) f.flags.hash = false;
// write if precision != 0 or value is != 0
if (!self.flags.precision || value)
if (!f.flags.precision || value)
{
char past_10 = (self.flags.uppercase ? 'A' : 'a') - 10;
char past_10 = (f.flags.uppercase ? 'A' : 'a') - 10;
switch (base)
{
case 2:
@@ -612,27 +633,26 @@ fn usz? Formatter.ntoa(&self, uint128 value, bool negative, uint base) @private
if (len >= PRINTF_NTOA_BUFFER_SIZE) return INTERNAL_BUFFER_EXCEEDED~;
buf[len++] = '0' + (char)value & 0x7;
value >>= 3;
}
while (value);
} while (value);
default:
unreachable();
}
}
return self.ntoa_format((String)buf[:PRINTF_NTOA_BUFFER_SIZE], len, negative, base);
return formatter_ntoa_format(f, (String)buf[:PRINTF_NTOA_BUFFER_SIZE], len, negative, base);
}
fn usz? Formatter.ntoa_format(&self, String buf, usz len, bool negative, uint base) @private
fn usz? formatter_ntoa_format(Formatter* f, String buf, usz len, bool negative, uint base) @private
{
// pad leading zeros
if (!self.flags.left)
if (!f.flags.left)
{
if (self.width && self.flags.zeropad && (negative || self.flags.plus || self.flags.space)) self.width--;
while (len < self.prec)
if (f.width && f.flags.zeropad && (negative || f.flags.plus || f.flags.space)) f.width--;
while (len < f.prec)
{
if (len >= buf.len) return INTERNAL_BUFFER_EXCEEDED~;
buf[len++] = '0';
}
while (self.flags.zeropad && len < self.width)
while (f.flags.zeropad && len < f.width)
{
if (len >= buf.len) return INTERNAL_BUFFER_EXCEEDED~;
buf[len++] = '0';
@@ -640,9 +660,9 @@ fn usz? Formatter.ntoa_format(&self, String buf, usz len, bool negative, uint ba
}
// handle hash
if (self.flags.hash && base != 10)
if (f.flags.hash && base != 10)
{
if (!self.flags.precision && len && len == self.prec && len == self.width)
if (!f.flags.precision && len && len == f.prec && len == f.width)
{
len--;
if (len) len--;
@@ -653,11 +673,11 @@ fn usz? Formatter.ntoa_format(&self, String buf, usz len, bool negative, uint ba
switch (base)
{
case 16:
buf[len++] = self.flags.uppercase ? 'X' : 'x';
buf[len++] = f.flags.uppercase ? 'X' : 'x';
case 8:
buf[len++] = self.flags.uppercase ? 'O' : 'o';
buf[len++] = f.flags.uppercase ? 'O' : 'o';
case 2:
buf[len++] = self.flags.uppercase ? 'B' : 'b';
buf[len++] = f.flags.uppercase ? 'B' : 'b';
default:
unreachable();
}
@@ -670,35 +690,35 @@ fn usz? Formatter.ntoa_format(&self, String buf, usz len, bool negative, uint ba
case negative:
if (len >= buf.len) return INTERNAL_BUFFER_EXCEEDED~;
buf[len++] = '-';
case self.flags.plus:
case f.flags.plus:
if (len >= buf.len) return INTERNAL_BUFFER_EXCEEDED~;
buf[len++] = '+';
case self.flags.space:
case f.flags.space:
if (len >= buf.len) return INTERNAL_BUFFER_EXCEEDED~;
buf[len++] = ' ';
}
if (len) self.out_reverse(buf[:len])!;
if (len) formatter_out_reverse(f, buf[:len])!;
return len;
}
fn usz? Formatter.ntoa_any(&self, any arg, uint base) @private
fn usz? formatter_ntoa_any(Formatter* f, any arg, uint base) @private
{
bool is_neg;
return self.ntoa(int_from_any(arg, &is_neg)!!, is_neg, base) @inline;
return formatter_ntoa(f, int_from_any(arg, &is_neg)!!, is_neg, base) @inline;
}
fn usz? Formatter.out_char(&self, any arg) @private
fn usz? formatter_out_char(Formatter* f, any arg) @private
{
if (!arg.type.kindof.is_int())
{
return self.out_substr("<NOT CHAR>");
return formatter_out_substr(f, "<NOT CHAR>");
}
usz len = 1;
// pre padding
if (!self.flags.left)
if (!f.flags.left)
{
len += self.pad(' ', self.width, len)!;
len += formatter_pad(f, ' ', f.width, len)!;
}
// char output
@@ -706,42 +726,42 @@ fn usz? Formatter.out_char(&self, any arg) @private
switch (true)
{
case c < 0x7f:
self.out((char)c)!;
f.print_char((char)c)!;
case c < 0x7ff:
self.out((char)(0xC0 | c >> 6))!;
self.out((char)(0x80 | (c & 0x3F)))!;
f.print_char((char)(0xC0 | c >> 6))!;
f.print_char((char)(0x80 | (c & 0x3F)))!;
case c < 0xffff:
self.out((char)(0xE0 | c >> 12))!;
self.out((char)(0x80 | (c >> 6 & 0x3F)))!;
self.out((char)(0x80 | (c & 0x3F)))!;
f.print_char((char)(0xE0 | c >> 12))!;
f.print_char((char)(0x80 | (c >> 6 & 0x3F)))!;
f.print_char((char)(0x80 | (c & 0x3F)))!;
default:
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)))!;
f.print_char((char)(0xF0 | c >> 18))!;
f.print_char((char)(0x80 | (c >> 12 & 0x3F)))!;
f.print_char((char)(0x80 | (c >> 6 & 0x3F)))!;
f.print_char((char)(0x80 | (c & 0x3F)))!;
}
if (self.flags.left)
if (f.flags.left)
{
len += self.pad(' ', self.width, len)!;
len += formatter_pad(f, ' ', f.width, len)!;
}
return len;
}
fn usz? Formatter.out_reverse(&self, char[] buf) @private
fn usz? formatter_out_reverse(Formatter* f, char[] buf) @private
{
usz n;
usz len = buf.len;
// pad spaces up to given width
if (!self.flags.zeropad && !self.flags.left)
if (!f.flags.zeropad && !f.flags.left)
{
n += self.pad(' ', self.width, len)!;
n += formatter_pad(f, ' ', f.width, len)!;
}
// reverse string
while (len) n += self.out(buf[--len])!;
while (len) n += f.print_char(buf[--len])!;
// append pad spaces up to given width
n += self.adjust(n)!;
n += formatter_adjust(f, n)!;
return n;
}
@@ -761,3 +781,197 @@ fn int? printf_parse_format_field(
uint? intval = types::any_to_int(val, int);
return intval ?? BAD_FORMAT~;
}
fn usz? formatter_out_hex_buffer(Formatter* self, any arg) @private @inline
{
char[] out @noinit;
switch (arg.type)
{
case char[]:
case ichar[]:
out = *(char[]*)arg;
default:
if (arg.type.kindof == ARRAY && (arg.type.inner == char.typeid || arg.type.inner == ichar.typeid))
{
out = ((char*)arg.ptr)[:arg.type.sizeof];
break;
}
if (arg.type.kindof == POINTER)
{
// Maybe there is a more idiomatic way here
out = ((*(char**)arg.ptr))[:arg.type.inner.sizeof];
break;
}
return formatter_out_substr(self, "<INVALID>");
}
usz len = out.len * 2;
usz total;
if (self.flags.left)
{
total += print_hex_chars(self, out, self.flags.uppercase)!;
total += formatter_pad(self, ' ', self.width, (isz)total)!;
}
else
{
if (self.width) total += formatter_pad(self, ' ', self.width, (isz)len)!;
total += print_hex_chars(self, out, self.flags.uppercase)!;
}
return total;
}
fn usz? formatter_out_unknown(Formatter* self, String category, any arg) @private
{
return formatter_out_substr(self, "<")
+ formatter_out_substr(self, category)
+ formatter_out_substr(self, " type:")
+ formatter_ntoa(self, (iptr)arg.type, false, 16)
+ formatter_out_substr(self, ", addr:")
+ formatter_ntoa(self, (iptr)arg.ptr, false, 16)
+ formatter_out_substr(self, ">");
}
fn usz? formatter_out_collection(Formatter* self, any arg, String open, String close) @private
{
typeid inner = arg.type.inner;
if (inner == void.typeid) inner = char.typeid;
usz size = inner.sizeof;
usz alen;
void* data_ptr;
if (arg.type.kindof == SLICE)
{
String* temp = arg.ptr;
data_ptr = temp.ptr;
alen = temp.len;
}
else
{
data_ptr = arg.ptr;
alen = arg.type.len;
}
PrintFlags flags = self.flags;
uint width = self.width;
defer
{
self.flags = flags;
self.width = width;
}
self.flags = {};
self.width = 0;
usz len = formatter_out_substr(self, open)!;
for (usz i = 0; i < alen; i++)
{
if (i != 0) len += formatter_out_substr(self, ", ")!;
len += formatter_out_str(self, any_make(data_ptr, inner))!;
data_ptr += size;
}
len += formatter_out_substr(self, close)!;
return len;
}
fn usz? formatter_out_str(Formatter* self, any arg) @private
{
switch (arg.type.kindof)
{
case VOID:
return formatter_out_substr(self, "void");
case FAULT:
fault f = *(fault*)arg.ptr;
return formatter_out_substr(self, f ? f.nameof : "(empty-fault)");
case INTERFACE:
any a = *(any*)arg;
return a ? formatter_out_str(self, a) : formatter_out_substr(self, "(empty-interface)");
case ANY:
any a = *(any*)arg;
return a ? formatter_out_str(self, a) : formatter_out_substr(self, "(empty-any)");
case OPTIONAL:
unreachable();
case SIGNED_INT:
case UNSIGNED_INT:
case FLOAT:
case FUNC:
case POINTER:
PrintFlags flags = self.flags;
uint width = self.width;
defer
{
self.flags = flags;
self.width = width;
}
self.flags = {};
self.width = 0;
switch (arg.type.kindof)
{
case SIGNED_INT:
case UNSIGNED_INT:
return formatter_ntoa_any(self, arg, 10) ?? formatter_out_substr(self, "<INVALID>");
case FLOAT:
return formatter_ftoa(self, float_from_any(arg)) ?? formatter_out_substr(self, "ERR");
case FUNC:
case POINTER:
if (arg.type.kindof == POINTER && arg.type.inner != void.typeid)
{
void** pointer = arg.ptr;
any deref = any_make(*pointer, arg.type.inner);
usz? n = self.print_with_function((Printable)deref);
if (try n) return n;
if (@catch(n) != NOT_FOUND) n!;
}
return formatter_out_substr(self, "0x")! + formatter_ntoa_any(self, arg, 16);
default:
unreachable();
}
case BOOL:
return formatter_out_substr(self, *(bool*)arg.ptr ? "true" : "false");
default:
}
usz? n = self.print_with_function((Printable)arg);
if (try n) return n;
if (@catch(n) != NOT_FOUND) n!;
switch (arg.type.kindof)
{
case TYPEID:
return formatter_out_substr(self, "typeid[")! + formatter_ntoa(self, (iptr)*(typeid*)arg, false, 16)! + formatter_out_substr(self, "]")!;
case ENUM:
usz i = types::any_to_enum_ordinal(arg, usz)!!;
assert(i < arg.type.names.len, "Illegal enum value found, numerical value was %d.", i);
return formatter_out_substr(self, arg.type.names[i]);
case STRUCT:
return formatter_out_unknown(self, "struct", arg);
case UNION:
return formatter_out_unknown(self, "union", arg);
case BITSTRUCT:
return formatter_out_unknown(self, "bitstruct", arg);
case CONST_ENUM:
case DISTINCT:
if (arg.type == String.typeid)
{
return formatter_out_substr(self, *(String*)arg);
}
if (arg.type == ZString.typeid)
{
return formatter_out_substr(self, *(ZString*)arg ? ((ZString*)arg).str_view() : "(null)");
}
if (arg.type == DString.typeid)
{
return formatter_out_substr(self, *(DString*)arg ? ((DString*)arg).str_view() : "(null)");
}
return formatter_out_str(self, arg.as_inner());
case ARRAY:
return formatter_out_collection(self, arg, "[", "]");
case VECTOR:
return formatter_out_collection(self, arg, "[<", ">]");
case SLICE:
return formatter_out_collection(self, arg, "[", "]");
case ANY:
case INTERFACE:
unreachable("Already handled");
default:
}
return formatter_out_substr(self, "Invalid type");
}

View File

@@ -366,7 +366,7 @@ fn usz? printfn(String format, args...) @format(0) @maydiscard
PutcharBuffer buff;
formatter.init(&out_putchar_buffer_fn, &buff);
usz? len = formatter.vprintf(format, args);
formatter.out('\n')!;
formatter.print_char('\n')!;
write_putchar_buffer(&buff, true)!;
return len + 1;
}

View File

@@ -38,7 +38,7 @@ fn usz? ReadBuffer.read(&self, char[] bytes) @dynamic
// Read directly into the input buffer.
return self.wrapped_stream.read(bytes)!;
}
self.refill()!;
readbuffer_refill(self)!;
}
usz n = min(self.write_idx - self.read_idx, bytes.len);
bytes[:n] = self.bytes[self.read_idx:n];
@@ -48,14 +48,14 @@ fn usz? ReadBuffer.read(&self, char[] bytes) @dynamic
fn char? ReadBuffer.read_byte(&self) @dynamic
{
if (self.read_idx == self.write_idx) self.refill()!;
if (self.read_idx == self.write_idx) readbuffer_refill(self)!;
if (self.read_idx == self.write_idx) return io::EOF~;
char c = self.bytes[self.read_idx];
self.read_idx++;
return c;
}
fn void? ReadBuffer.refill(&self) @local @inline
fn void? readbuffer_refill(ReadBuffer* self) @local @inline
{
self.read_idx = 0;
self.write_idx = self.wrapped_stream.read(self.bytes)!;
@@ -92,7 +92,7 @@ fn void? WriteBuffer.close(&self) @dynamic
fn void? WriteBuffer.flush(&self) @dynamic
{
self.write_pending()!;
write_buffer_write_pending(self)!;
if (&self.wrapped_stream.flush) self.wrapped_stream.flush()!;
}
@@ -106,7 +106,7 @@ fn usz? WriteBuffer.write(&self, char[] bytes) @dynamic
self.index += bytes.len;
return bytes.len;
}
self.write_pending()!;
write_buffer_write_pending(self)!;
if (bytes.len >= self.bytes.len)
{
// Write directly to the stream.
@@ -123,13 +123,13 @@ fn void? WriteBuffer.write_byte(&self, char c) @dynamic
usz n = self.bytes.len - self.index;
if (n == 0)
{
self.write_pending()!;
write_buffer_write_pending(self)!;
}
self.bytes[self.index] = c;
self.index += 1;
}
fn void? WriteBuffer.write_pending(&self) @local
fn void? write_buffer_write_pending(WriteBuffer* self) @local
{
self.index -= self.wrapped_stream.write(self.bytes[:self.index])!;
if (self.index != 0) return INCOMPLETE_WRITE~;