mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 03:51:18 +00:00
some refactoring of io formatter internals
extracted logic for hex-buffers (%h), string-padding (%s), hex-floats (%a), and collection printing into helper functions.
This commit is contained in:
committed by
Christoffer Lerno
parent
9fbf6bc213
commit
7ae4c5a1ab
@@ -139,6 +139,47 @@ 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(">");
|
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
|
fn usz? Formatter.out_str(&self, any arg) @private
|
||||||
{
|
{
|
||||||
switch (arg.type.kindof)
|
switch (arg.type.kindof)
|
||||||
@@ -158,17 +199,9 @@ fn usz? Formatter.out_str(&self, any arg) @private
|
|||||||
unreachable();
|
unreachable();
|
||||||
case SIGNED_INT:
|
case SIGNED_INT:
|
||||||
case UNSIGNED_INT:
|
case UNSIGNED_INT:
|
||||||
PrintFlags flags = self.flags;
|
|
||||||
uint width = self.width;
|
|
||||||
defer
|
|
||||||
{
|
|
||||||
self.flags = flags;
|
|
||||||
self.width = width;
|
|
||||||
}
|
|
||||||
self.flags = {};
|
|
||||||
self.width = 0;
|
|
||||||
return self.ntoa_any(arg, 10) ?? self.out_substr("<INVALID>");
|
|
||||||
case FLOAT:
|
case FLOAT:
|
||||||
|
case FUNC:
|
||||||
|
case POINTER:
|
||||||
PrintFlags flags = self.flags;
|
PrintFlags flags = self.flags;
|
||||||
uint width = self.width;
|
uint width = self.width;
|
||||||
defer
|
defer
|
||||||
@@ -178,7 +211,27 @@ fn usz? Formatter.out_str(&self, any arg) @private
|
|||||||
}
|
}
|
||||||
self.flags = {};
|
self.flags = {};
|
||||||
self.width = 0;
|
self.width = 0;
|
||||||
return self.ftoa(float_from_any(arg)) ?? self.out_substr("ERR");
|
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:
|
case BOOL:
|
||||||
return self.out_substr(*(bool*)arg.ptr ? "true" : "false");
|
return self.out_substr(*(bool*)arg.ptr ? "true" : "false");
|
||||||
default:
|
default:
|
||||||
@@ -200,16 +253,6 @@ fn usz? Formatter.out_str(&self, any arg) @private
|
|||||||
return self.out_unknown("union", arg);
|
return self.out_unknown("union", arg);
|
||||||
case BITSTRUCT:
|
case BITSTRUCT:
|
||||||
return self.out_unknown("bitstruct", arg);
|
return self.out_unknown("bitstruct", arg);
|
||||||
case FUNC:
|
|
||||||
PrintFlags flags = self.flags;
|
|
||||||
uint width = self.width;
|
|
||||||
defer
|
|
||||||
{
|
|
||||||
self.flags = flags;
|
|
||||||
self.width = width;
|
|
||||||
}
|
|
||||||
self.width = 0;
|
|
||||||
return self.out_substr("0x")! + self.ntoa_any(arg, 16);
|
|
||||||
case CONST_ENUM:
|
case CONST_ENUM:
|
||||||
case DISTINCT:
|
case DISTINCT:
|
||||||
if (arg.type == String.typeid)
|
if (arg.type == String.typeid)
|
||||||
@@ -225,102 +268,12 @@ fn usz? Formatter.out_str(&self, any arg) @private
|
|||||||
return self.out_substr(*(DString*)arg ? ((DString*)arg).str_view() : "(null)");
|
return self.out_substr(*(DString*)arg ? ((DString*)arg).str_view() : "(null)");
|
||||||
}
|
}
|
||||||
return self.out_str(arg.as_inner());
|
return self.out_str(arg.as_inner());
|
||||||
case POINTER:
|
|
||||||
typeid inner = arg.type.inner;
|
|
||||||
void** pointer = arg.ptr;
|
|
||||||
if (arg.type.inner != void.typeid)
|
|
||||||
{
|
|
||||||
any deref = any_make(*pointer, inner);
|
|
||||||
n = self.print_with_function((Printable)deref);
|
|
||||||
if (try n) return n;
|
|
||||||
if (@catch(n) != NOT_FOUND) n!;
|
|
||||||
}
|
|
||||||
PrintFlags flags = self.flags;
|
|
||||||
uint width = self.width;
|
|
||||||
defer
|
|
||||||
{
|
|
||||||
self.flags = flags;
|
|
||||||
self.width = width;
|
|
||||||
}
|
|
||||||
self.width = 0;
|
|
||||||
return self.out_substr("0x")! + self.ntoa_any(arg, 16);
|
|
||||||
case ARRAY:
|
case ARRAY:
|
||||||
// this is SomeType[*] so grab the "SomeType"
|
return self.out_collection(arg, "[", "]");
|
||||||
PrintFlags flags = self.flags;
|
|
||||||
uint width = self.width;
|
|
||||||
defer
|
|
||||||
{
|
|
||||||
self.flags = flags;
|
|
||||||
self.width = width;
|
|
||||||
}
|
|
||||||
self.flags = {};
|
|
||||||
self.width = 0;
|
|
||||||
typeid inner = arg.type.inner;
|
|
||||||
usz size = inner.sizeof;
|
|
||||||
usz alen = arg.type.len;
|
|
||||||
// Pretend this is a String
|
|
||||||
void* ptr = (void*)arg.ptr;
|
|
||||||
usz len = self.out('[')!;
|
|
||||||
for (usz i = 0; i < alen; i++)
|
|
||||||
{
|
|
||||||
if (i != 0) len += self.out_substr(", ")!;
|
|
||||||
len += self.out_str(any_make(ptr, inner))!;
|
|
||||||
ptr += size;
|
|
||||||
}
|
|
||||||
len += self.out(']')!;
|
|
||||||
return len;
|
|
||||||
case VECTOR:
|
case VECTOR:
|
||||||
PrintFlags flags = self.flags;
|
return self.out_collection(arg, "[<", ">]");
|
||||||
uint width = self.width;
|
|
||||||
defer
|
|
||||||
{
|
|
||||||
self.flags = flags;
|
|
||||||
self.width = width;
|
|
||||||
}
|
|
||||||
self.flags = {};
|
|
||||||
self.width = 0;
|
|
||||||
// this is SomeType[*] so grab the "SomeType"
|
|
||||||
typeid inner = arg.type.inner;
|
|
||||||
usz size = inner.sizeof;
|
|
||||||
usz vlen = arg.type.len;
|
|
||||||
// Pretend this is a String
|
|
||||||
void* ptr = (void*)arg.ptr;
|
|
||||||
usz len = self.out_substr("[<")!;
|
|
||||||
for (usz i = 0; i < vlen; i++)
|
|
||||||
{
|
|
||||||
if (i != 0) len += self.out_substr(", ")!;
|
|
||||||
len += self.out_str(any_make(ptr, inner))!;
|
|
||||||
ptr += size;
|
|
||||||
}
|
|
||||||
len += self.out_substr(">]")!;
|
|
||||||
return len;
|
|
||||||
case SLICE:
|
case SLICE:
|
||||||
// this is SomeType[] so grab the "SomeType"
|
return self.out_collection(arg, "[", "]");
|
||||||
typeid inner = arg.type.inner;
|
|
||||||
if (inner == void.typeid) inner = char.typeid;
|
|
||||||
PrintFlags flags = self.flags;
|
|
||||||
uint width = self.width;
|
|
||||||
defer
|
|
||||||
{
|
|
||||||
self.flags = flags;
|
|
||||||
self.width = width;
|
|
||||||
}
|
|
||||||
self.flags = {};
|
|
||||||
self.width = 0;
|
|
||||||
usz size = inner.sizeof;
|
|
||||||
// Pretend this is a String
|
|
||||||
String* temp = (void*)arg.ptr;
|
|
||||||
void* ptr = (void*)temp.ptr;
|
|
||||||
usz slen = temp.len;
|
|
||||||
usz len = self.out('[')!;
|
|
||||||
for (usz i = 0; i < slen; i++)
|
|
||||||
{
|
|
||||||
if (i != 0) len += self.out_substr(", ")!;
|
|
||||||
len += self.out_str(any_make(ptr, inner))!;
|
|
||||||
ptr += size;
|
|
||||||
}
|
|
||||||
len += self.out(']')!;
|
|
||||||
return len;
|
|
||||||
case ANY:
|
case ANY:
|
||||||
case INTERFACE:
|
case INTERFACE:
|
||||||
unreachable("Already handled");
|
unreachable("Already handled");
|
||||||
@@ -361,6 +314,63 @@ macro usz? @wrap_bad(Formatter* f, #action)
|
|||||||
return len;
|
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)
|
fn usz? Formatter.vprintf(&self, String format, any[] anys)
|
||||||
{
|
{
|
||||||
self.first_fault = {};
|
self.first_fault = {};
|
||||||
@@ -415,7 +425,7 @@ fn usz? Formatter.vprintf(&self, String format, any[] anys)
|
|||||||
self.flags.left = true;
|
self.flags.left = true;
|
||||||
w = -w;
|
w = -w;
|
||||||
}
|
}
|
||||||
self.width = w;
|
self.width = (uint)w;
|
||||||
// evaluate precision field
|
// evaluate precision field
|
||||||
self.prec = 0;
|
self.prec = 0;
|
||||||
if (c == '.')
|
if (c == '.')
|
||||||
@@ -424,7 +434,7 @@ fn usz? Formatter.vprintf(&self, String format, any[] anys)
|
|||||||
if (++i >= format_len) return @report_fault(self, "<BAD FORMAT>");
|
if (++i >= format_len) return @report_fault(self, "<BAD FORMAT>");
|
||||||
int? prec = printf_parse_format_field(anys.ptr, anys.len, &variant_index, format.ptr, format.len, &i);
|
int? prec = printf_parse_format_field(anys.ptr, anys.len, &variant_index, format.ptr, format.len, &i);
|
||||||
if (catch prec) return @report_fault(self, "<BAD FORMAT>");
|
if (catch prec) return @report_fault(self, "<BAD FORMAT>");
|
||||||
self.prec = prec < 0 ? 0 : prec;
|
self.prec = (uint)(prec < 0 ? 0 : prec);
|
||||||
c = format[i];
|
c = format[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -488,56 +498,10 @@ fn usz? Formatter.vprintf(&self, String format, any[] anys)
|
|||||||
self.flags.uppercase = true;
|
self.flags.uppercase = true;
|
||||||
nextcase;
|
nextcase;
|
||||||
case 'h':
|
case 'h':
|
||||||
char[] out @noinit;
|
total_len += self.out_hex_buffer(current)!;
|
||||||
switch (current.type)
|
|
||||||
{
|
|
||||||
case char[]:
|
|
||||||
case ichar[]:
|
|
||||||
out = *(char[]*)current;
|
|
||||||
default:
|
|
||||||
if (current.type.kindof == ARRAY && (current.type.inner == char.typeid || current.type.inner == ichar.typeid))
|
|
||||||
{
|
|
||||||
out = ((char*)current.ptr)[:current.type.sizeof];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (current.type.kindof == POINTER)
|
|
||||||
{
|
|
||||||
out = ((*(char**)current.ptr))[:current.type.inner.sizeof];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
total_len += self.out_substr("<INVALID>")!;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (self.flags.left)
|
|
||||||
{
|
|
||||||
usz len = print_hex_chars(self, out, self.flags.uppercase)!;
|
|
||||||
total_len += len;
|
|
||||||
total_len += self.pad(' ', self.width, len)!;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (self.width)
|
|
||||||
{
|
|
||||||
total_len += self.pad(' ', self.width, out.len * 2)!;
|
|
||||||
}
|
|
||||||
total_len += print_hex_chars(self, out, self.flags.uppercase)!;
|
|
||||||
continue;
|
continue;
|
||||||
case 's':
|
case 's':
|
||||||
if (self.flags.left)
|
total_len += self.out_str_pad(current)!;
|
||||||
{
|
|
||||||
usz len = self.out_str(current)!;
|
|
||||||
total_len += len;
|
|
||||||
total_len += self.pad(' ', self.width, len)!;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (self.width)
|
|
||||||
{
|
|
||||||
OutputFn out_fn = self.out_fn;
|
|
||||||
self.out_fn = (OutputFn)&out_null_fn;
|
|
||||||
usz len = self.out_str(current)!;
|
|
||||||
self.out_fn = out_fn;
|
|
||||||
total_len += self.pad(' ', self.width, len)!;
|
|
||||||
}
|
|
||||||
total_len += self.out_str(current)!;
|
|
||||||
continue;
|
continue;
|
||||||
case 'p':
|
case 'p':
|
||||||
self.flags.zeropad = true;
|
self.flags.zeropad = true;
|
||||||
@@ -559,10 +523,7 @@ fn usz? Formatter.vprintf(&self, String format, any[] anys)
|
|||||||
bool is_neg;
|
bool is_neg;
|
||||||
total_len += @wrap_bad(self, self.ntoa(int_from_any(current, &is_neg), is_neg, base))!;
|
total_len += @wrap_bad(self, self.ntoa(int_from_any(current, &is_neg), is_neg, base))!;
|
||||||
}
|
}
|
||||||
// termination
|
|
||||||
// out((char)0, buffer, idx < maxlen ? idx : maxlen - 1U, maxlen);
|
|
||||||
|
|
||||||
// return written chars without terminating \0
|
|
||||||
if (self.first_fault) return self.first_fault~;
|
if (self.first_fault) return self.first_fault~;
|
||||||
return total_len;
|
return total_len;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -208,6 +208,70 @@ 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.gtoa(&self, double y) => self.floatformat(ADAPTIVE, y);
|
||||||
fn usz? Formatter.atoa(&self, double y) => self.floatformat(HEX, y);
|
fn usz? Formatter.atoa(&self, double y) => self.floatformat(HEX, y);
|
||||||
|
|
||||||
|
fn usz? Formatter.floatformat_hex(&self, double y, bool is_neg, isz pl, isz p) @private @inline
|
||||||
|
{
|
||||||
|
double round = 8.0;
|
||||||
|
// 0x / 0X
|
||||||
|
pl += 2;
|
||||||
|
if (p > 0 && p < math::DOUBLE_MANT_DIG / 4 - 1)
|
||||||
|
{
|
||||||
|
int re = math::DOUBLE_MANT_DIG / 4 - 1 - (int)p;
|
||||||
|
round *= 1 << (math::DOUBLE_MANT_DIG % 4);
|
||||||
|
while (re--) round *= 16;
|
||||||
|
if (is_neg)
|
||||||
|
{
|
||||||
|
y = -y;
|
||||||
|
y -= round;
|
||||||
|
y += round;
|
||||||
|
y = -y;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
y += round;
|
||||||
|
y -= round;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int e2;
|
||||||
|
y = math::frexp(y, &e2) * 2;
|
||||||
|
if (y) e2--;
|
||||||
|
char[12] ebuf0;
|
||||||
|
char* ebuf = &ebuf0[0] + 12;
|
||||||
|
char[9 + math::DOUBLE_MANT_DIG / 4] buf_array;
|
||||||
|
char* buf = &buf_array[0];
|
||||||
|
|
||||||
|
// Reverse print
|
||||||
|
char* estr = fmt_u(e2 < 0 ? (int128)-e2 : (int128)e2, ebuf);
|
||||||
|
if (estr == ebuf) *--estr = '0';
|
||||||
|
*--estr = (e2 < 0 ? '-' : '+');
|
||||||
|
*--estr = self.flags.uppercase ? 'P' : 'p';
|
||||||
|
char* s = buf;
|
||||||
|
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 || self.flags.hash)) *s++ = '.';
|
||||||
|
if (p >= 0 && (s - buf) >= (2 + p)) break;
|
||||||
|
} while (y);
|
||||||
|
isz outlen = s - buf;
|
||||||
|
isz explen = ebuf - estr;
|
||||||
|
if (p > int.max - 2 - explen - pl) return INTERNAL_BUFFER_EXCEEDED~;
|
||||||
|
usz len;
|
||||||
|
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 ? '-' : '+')!;
|
||||||
|
len += self.out_chars(self.flags.uppercase ? "0X" : "0x")!;
|
||||||
|
if (self.flags.zeropad) len += self.pad('0', self.width, pl + l)!;
|
||||||
|
len += self.out_chars(buf[:outlen])!;
|
||||||
|
len += self.pad('0', (isz)l - outlen - explen, 0)!;
|
||||||
|
len += self.out_chars(estr[:explen])!;
|
||||||
|
if (self.flags.left) len += self.pad(' ', self.width, pl + (isz)l)!;
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
fn usz? Formatter.floatformat(&self, FloatFormatting formatting, double y) @private
|
fn usz? Formatter.floatformat(&self, FloatFormatting formatting, double y) @private
|
||||||
{
|
{
|
||||||
// This code is heavily based on musl's printf code
|
// This code is heavily based on musl's printf code
|
||||||
@@ -234,70 +298,15 @@ fn usz? Formatter.floatformat(&self, FloatFormatting formatting, double y) @priv
|
|||||||
if (self.flags.left) len += self.pad(' ', self.width, 3 + pl)!;
|
if (self.flags.left) len += self.pad(' ', self.width, 3 + pl)!;
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isz p = self.flags.precision ? self.prec : -1;
|
||||||
|
if (formatting == HEX) return self.floatformat_hex(y, is_neg, pl, p);
|
||||||
|
|
||||||
// Rescale
|
// Rescale
|
||||||
int e2;
|
int e2;
|
||||||
|
|
||||||
y = math::frexp(y, &e2) * 2;
|
y = math::frexp(y, &e2) * 2;
|
||||||
if (y) e2--;
|
if (y) e2--;
|
||||||
char[12] ebuf0;
|
|
||||||
char* ebuf = 12 + (char*)&ebuf0;
|
|
||||||
char[9 + math::DOUBLE_MANT_DIG / 4] buf_array;
|
|
||||||
char* buf = &buf_array;
|
|
||||||
isz p = self.flags.precision ? self.prec : -1;
|
|
||||||
if (formatting == HEX)
|
|
||||||
{
|
|
||||||
double round = 8.0;
|
|
||||||
// 0x / 0X
|
|
||||||
pl += 2;
|
|
||||||
if (p > 0 && p < math::DOUBLE_MANT_DIG / 4 - 1)
|
|
||||||
{
|
|
||||||
int re = math::DOUBLE_MANT_DIG / 4 - 1 - (int)p;
|
|
||||||
round *= 1 << (math::DOUBLE_MANT_DIG % 4);
|
|
||||||
while (re--) round *= 16;
|
|
||||||
if (is_neg)
|
|
||||||
{
|
|
||||||
y = -y;
|
|
||||||
y -= round;
|
|
||||||
y += round;
|
|
||||||
y = -y;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
y += round;
|
|
||||||
y -= round;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Reverse print
|
|
||||||
char* estr = fmt_u(e2 < 0 ? (int128)-e2 : (int128)e2, ebuf);
|
|
||||||
if (estr == ebuf) *--estr = '0';
|
|
||||||
*--estr = (e2 < 0 ? '-' : '+');
|
|
||||||
*--estr = self.flags.uppercase ? 'P' : 'p';
|
|
||||||
char* s = buf;
|
|
||||||
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 || self.flags.hash)) *s++ = '.';
|
|
||||||
} while (y);
|
|
||||||
isz outlen = s - buf;
|
|
||||||
isz explen = ebuf - estr;
|
|
||||||
if (p > int.max - 2 - explen - pl) return INTERNAL_BUFFER_EXCEEDED~;
|
|
||||||
usz len;
|
|
||||||
usz l = 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 ? '-' : '+')!;
|
|
||||||
len += self.out_chars(self.flags.uppercase ? "0X" : "0x")!;
|
|
||||||
if (self.flags.zeropad) len += self.pad('0', self.width, pl + l)!;
|
|
||||||
len += self.out_chars(buf[:outlen])!;
|
|
||||||
len += self.pad('0', l - outlen - explen, 0)!;
|
|
||||||
len += self.out_chars(estr[:explen])!;
|
|
||||||
if (self.flags.left) len += self.pad(' ', self.width, pl + l)!;
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
if (p < 0) p = 6;
|
if (p < 0) p = 6;
|
||||||
if (y)
|
if (y)
|
||||||
{
|
{
|
||||||
@@ -344,7 +353,6 @@ fn usz? Formatter.floatformat(&self, FloatFormatting formatting, double y) @priv
|
|||||||
int need = (int)(1 + (p + math::DOUBLE_MANT_DIG / 3u + 8) / 9);
|
int need = (int)(1 + (p + math::DOUBLE_MANT_DIG / 3u + 8) / 9);
|
||||||
for (uint* d = a; d < z; d++)
|
for (uint* d = a; d < z; d++)
|
||||||
{
|
{
|
||||||
// CHECK THIS
|
|
||||||
uint rm = *d & ((1 << sh) - 1);
|
uint rm = *d & ((1 << sh) - 1);
|
||||||
*d = (*d >> sh) + carry;
|
*d = (*d >> sh) + carry;
|
||||||
carry = (1000000000 >> sh) * rm;
|
carry = (1000000000 >> sh) * rm;
|
||||||
@@ -456,6 +464,8 @@ fn usz? Formatter.floatformat(&self, FloatFormatting formatting, double y) @priv
|
|||||||
}
|
}
|
||||||
if (p > int.max - 1 - (isz)(p || self.flags.hash)) return INTERNAL_BUFFER_EXCEEDED~;
|
if (p > int.max - 1 - (isz)(p || self.flags.hash)) return INTERNAL_BUFFER_EXCEEDED~;
|
||||||
int l = (int)(1 + p + (isz)(p || self.flags.hash));
|
int l = (int)(1 + p + (isz)(p || self.flags.hash));
|
||||||
|
char[12] ebuf0;
|
||||||
|
char* ebuf = &ebuf0[0] + 12;
|
||||||
char* estr @noinit;
|
char* estr @noinit;
|
||||||
if (formatting == FLOAT)
|
if (formatting == FLOAT)
|
||||||
{
|
{
|
||||||
@@ -476,6 +486,10 @@ fn usz? Formatter.floatformat(&self, FloatFormatting formatting, double y) @priv
|
|||||||
if (!self.flags.left && !self.flags.zeropad) len += self.pad(' ', self.width, pl + l)!;
|
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 (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.zeropad) len += self.pad('0', self.width, pl + l)!;
|
||||||
|
|
||||||
|
char[9] buf_array;
|
||||||
|
char* buf = &buf_array[0];
|
||||||
|
|
||||||
if (formatting == FLOAT)
|
if (formatting == FLOAT)
|
||||||
{
|
{
|
||||||
if (a > r) a = r;
|
if (a > r) a = r;
|
||||||
|
|||||||
Reference in New Issue
Block a user