mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
- Warn on use of visibility modifiers on methods. #2962
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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~;
|
||||
|
||||
Reference in New Issue
Block a user