Files
TransPyC/includes/viperlib.py
2026-07-18 19:25:40 +08:00

1365 lines
55 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import t, c
import viperio
from stdarg import arg, va_arg
TEMP_BUF_SIZE: t.CDefine = 68
def get_digit_count(num: t.CUnsignedInt, base: t.CInt) -> t.CStatic | t.CInt:
count: t.CInt = 0
if num == 0: return 1
while num > 0:
count += 1
num //= base
return count
def sprintf(buf: t.CChar | t.CPtr, rule: str, *args) -> t.CVoid | t.CExport:
if buf is None or rule is None: return
vsnprintf(buf, 0x7FFFFFFF, rule, args)
def vsprintf(buf: t.CChar | t.CPtr, rule: str, *args) -> t.CInt:
if buf is None or rule is None: return 0
return vsnprintf(buf, 0x7FFFFFFF, rule, args)
def snprintf(buf: t.CChar | t.CPtr, size: t.CSizeT, fmt: str, *args) -> t.CInt | t.CExport:
if buf is None or fmt is None or size == 0: return 0
return vsnprintf(buf, size, fmt, args)
# 检测浮点特殊值IEEE 754
# 返回: 0=normal, 1=+inf, 2=-inf, 3=nan
def _check_special_float(fv: t.CDouble) -> t.CInt:
fbits: t.CUInt64T = 0
c.Load(c.Addr(fbits), c.Addr(fv))
if ((fbits >> 52) & 0x7FF) != 0x7FF:
return 0
is_neg: t.CInt = 1 if (fbits >> 63) != 0 else 0
if (fbits & 0x000FFFFFFFFFFFFF) == 0:
if is_neg:
return 2
return 1
return 3
def vsnprintf(buf: t.CChar | t.CPtr, size: t.CSizeT, fmt: str, ap: t.CChar | t.CPtr) -> t.CInt | t.CExport:
if buf is None or fmt is None or size == 0: return 0
ptr: t.CChar | t.CPtr = buf
write_count: t.CInt = 0
temp: t.CArray[t.CChar, 68]
temp[0] = '\t'
while c.Deref(fmt) != 0 and write_count < size - 1:
if c.Deref(fmt) != 37:
ptr[0] = c.Deref(fmt)
write_count += 1
ptr += 1
fmt += 1
else:
fmt += 1
if c.Deref(fmt) == 0: break
width: t.CInt = 0
pad_zero: t.CInt = 0
left_align: t.CInt = 0
show_sign: t.CInt = 0
space_sign: t.CInt = 0
alt_form: t.CInt = 0
precision: t.CInt = -1
is_long: t.CInt = 0
is_long_long: t.CInt = 0
is_size: t.CInt = 0
is_short: t.CInt = 0
is_char: t.CInt = 0
while True:
if c.Deref(fmt) == 45:
left_align = 1
fmt += 1
elif c.Deref(fmt) == 48:
pad_zero = 1
fmt += 1
elif c.Deref(fmt) == 43:
show_sign = 1
fmt += 1
elif c.Deref(fmt) == 32:
space_sign = 1
fmt += 1
elif c.Deref(fmt) == 35:
alt_form = 1
fmt += 1
else: break
if show_sign: space_sign = 0
while c.Deref(fmt) >= 48 and c.Deref(fmt) <= 57:
width = width * 10 + (c.Deref(fmt) - 48)
fmt += 1
if c.Deref(fmt) == 46:
fmt += 1
precision = 0
while c.Deref(fmt) >= 48 and c.Deref(fmt) <= 57:
precision = precision * 10 + (c.Deref(fmt) - 48)
fmt += 1
if left_align: pad_zero = 0
if c.Deref(fmt) == 108:
is_long = 1
fmt += 1
if c.Deref(fmt) == 108:
is_long_long = 1
is_long = 0
fmt += 1
elif c.Deref(fmt) == 104:
is_short = 1
fmt += 1
if c.Deref(fmt) == 104:
is_char = 1
is_short = 0
fmt += 1
elif c.Deref(fmt) == 122:
is_size = 1
fmt += 1
elif c.Deref(fmt) == 106:
is_long_long = 1
fmt += 1
elif c.Deref(fmt) == 116:
is_long = 1
fmt += 1
if c.Deref(fmt) == 99:
if write_count < size - 1:
ptr_i: t.CInt = va_arg(ap)
ptr[0] = t.CChar(ptr_i)
write_count += 1
ptr += 1
else:
ptr_i: t.CInt = va_arg(ap)
elif c.Deref(fmt) == 115:
s: str = va_arg(ap, t.CPtr)
if s is None: s = "(None)"
slen: t.CInt = 0
sc: str = s
while c.Deref(sc) != 0:
slen += 1
sc += 1
if not left_align and width > slen:
pad_count: t.CInt = width - slen
while pad_count > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += 1
pad_count -= 1
while c.Deref(s) != 0 and write_count < size - 1:
ptr[0] = c.Deref(s)
write_count += 1
ptr += 1
s += 1
if left_align and width > slen:
pad_count = width - slen
while pad_count > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += 1
pad_count -= 1
elif c.Deref(fmt) == 100 or c.Deref(fmt) == 105:
if is_long_long or is_size or is_long:
num_l: t.CInt64T = va_arg(ap, t.CInt64T)
else:
num_l: t.CInt64T = t.CInt64T(va_arg(ap, t.CInt))
if is_char:
num_l = t.CInt64T(t.CChar(num_l))
elif is_short:
num_l = t.CInt64T(t.CShort(num_l))
sign: t.CInt = 0
if num_l < 0:
sign = 1
if num_l == (-9223372036854775807 - 1):
u_num: t.CUInt64T = t.CUInt64T(0x8000000000000000)
else:
u_num: t.CUInt64T = t.CUInt64T(-num_l)
else:
u_num: t.CUInt64T = t.CUInt64T(num_l)
if show_sign: sign = 2
elif space_sign: sign = 3
i: t.CInt = 0
while True:
if i >= TEMP_BUF_SIZE - 1: break
temp[i] = t.CChar(u_num % 10 + 48)
i += 1
u_num //= 10
if u_num <= 0: break
if sign == 1 and i < TEMP_BUF_SIZE - 1:
temp[i] = 45
i += 1
elif sign == 2 and i < TEMP_BUF_SIZE - 1:
temp[i] = 43
i += 1
elif sign == 3 and i < TEMP_BUF_SIZE - 1:
temp[i] = 32
i += 1
if not left_align and not pad_zero and width > i:
pad_count = width - i
while pad_count > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += 1
pad_count -= 1
if pad_zero and width > i:
pad_count = width - i
while pad_count > 0 and write_count < size - 1:
ptr[0] = 48
write_count += 1
ptr += 1
pad_count -= 1
while i > 0 and write_count < size - 1:
i -= 1
ptr[0] = temp[i]
write_count += 1
ptr += 1
if left_align and width > i:
pad_count = width - i
while pad_count > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += 1
pad_count -= 1
elif c.Deref(fmt) == 117:
if is_long or is_long_long or is_size:
u_num_l: t.CUInt64T = va_arg(ap, t.CUInt64T)
else:
u_num_l: t.CUInt64T = t.CUInt64T(t.CUnsignedInt(va_arg(ap)))
i = 0
while True:
if i >= TEMP_BUF_SIZE - 1: break
temp[i] = t.CChar(u_num_l % 10 + 48)
i += 1
u_num_l //= 10
if u_num_l <= 0: break
if not left_align and not pad_zero and width > i:
pad_count = width - i
while pad_count > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += 1
pad_count -= 1
if pad_zero and width > i:
pad_count = width - i
while pad_count > 0 and write_count < size - 1:
ptr[0] = 48
write_count += 1
ptr += 1
pad_count -= 1
while i > 0 and write_count < size - 1:
i -= 1
ptr[0] = temp[i]
write_count += 1
ptr += 1
if left_align and width > i:
pad_count = width - i
while pad_count > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += 1
pad_count -= 1
elif c.Deref(fmt) == 120:
if is_long or is_long_long or is_size:
u_num_l: t.CUInt64T = va_arg(ap, t.CUInt64T)
else:
u_num_l: t.CUInt64T = t.CUInt64T(t.CUnsignedInt(va_arg(ap)))
is_nonzero: t.CInt = 0
if u_num_l != 0:
is_nonzero = 1
i = 0
while True:
if i >= TEMP_BUF_SIZE - 1: break
digit: t.CInt = t.CInt(u_num_l % 16)
if digit < 10:
temp[i] = t.CChar(digit + 48)
else:
temp[i] = t.CChar(digit - 10 + 97)
u_num_l //= 16
i += 1
if u_num_l <= 0: break
digit_count: t.CInt = i
prefix_len: t.CInt = 0
if alt_form and is_nonzero:
prefix_len = 2
effective_len: t.CInt = digit_count + prefix_len
if not left_align and not pad_zero and width > effective_len:
pad_count = width - effective_len
while pad_count > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += 1
pad_count -= 1
if prefix_len > 0:
if write_count < size - 1:
ptr[0] = 48
write_count += 1
ptr += 1
if write_count < size - 1:
ptr[0] = 120
write_count += 1
ptr += 1
if pad_zero and width > effective_len:
pad_count = width - effective_len
while pad_count > 0 and write_count < size - 1:
ptr[0] = 48
write_count += 1
ptr += 1
pad_count -= 1
while i > 0 and write_count < size - 1:
i -= 1
ptr[0] = temp[i]
write_count += 1
ptr += 1
if left_align and width > effective_len:
pad_count = width - effective_len
while pad_count > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += 1
pad_count -= 1
elif c.Deref(fmt) == 88:
if is_long or is_long_long or is_size:
u_num_l: t.CUInt64T = va_arg(ap)
else:
u_num_l: t.CUInt64T = t.CUInt64T(t.CUnsignedInt(va_arg(ap)))
is_nonzero = 0
if u_num_l != 0:
is_nonzero = 1
i = 0
while True:
if i >= TEMP_BUF_SIZE - 1: break
digit = t.CInt(u_num_l % 16)
if digit < 10:
temp[i] = t.CChar(digit + 48)
else:
temp[i] = t.CChar(digit - 10 + 65)
u_num_l //= 16
i += 1
if u_num_l <= 0: break
digit_count = i
prefix_len = 0
if alt_form and is_nonzero:
prefix_len = 2
effective_len = digit_count + prefix_len
if not left_align and not pad_zero and width > effective_len:
pad_count = width - effective_len
while pad_count > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += 1
pad_count -= 1
if prefix_len > 0:
if write_count < size - 1:
ptr[0] = 48
write_count += 1
ptr += 1
if write_count < size - 1:
ptr[0] = 88
write_count += 1
ptr += 1
if pad_zero and width > effective_len:
pad_count = width - effective_len
while pad_count > 0 and write_count < size - 1:
ptr[0] = 48
write_count += 1
ptr += 1
pad_count -= 1
while i > 0 and write_count < size - 1:
i -= 1
ptr[0] = temp[i]
write_count += 1
ptr += 1
if left_align and width > effective_len:
pad_count = width - effective_len
while pad_count > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += 1
pad_count -= 1
elif c.Deref(fmt) == 111:
if is_long or is_long_long or is_size:
u_num_l: t.CUInt64T = va_arg(ap, t.CUInt64T)
else:
u_num_l: t.CUInt64T = t.CUInt64T(t.CUnsignedInt(va_arg(ap)))
if is_char:
u_num_l = t.CUInt64T(t.CChar(u_num_l))
elif is_short:
u_num_l = t.CUInt64T(t.CShort(u_num_l))
i = 0
if u_num_l == 0 and not alt_form:
temp[0] = 48
i = 1
else:
while True:
if i >= TEMP_BUF_SIZE - 1: break
temp[i] = t.CChar(u_num_l % 8 + 48)
i += 1
u_num_l //= 8
if u_num_l <= 0: break
if alt_form and i < TEMP_BUF_SIZE - 1:
temp[i] = 48
i += 1
if not left_align and not pad_zero and width > i:
pad_count = width - i
while pad_count > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += 1
pad_count -= 1
if pad_zero and width > i:
pad_count = width - i
while pad_count > 0 and write_count < size - 1:
ptr[0] = 48
write_count += 1
ptr += 1
pad_count -= 1
while i > 0 and write_count < size - 1:
i -= 1
ptr[0] = temp[i]
write_count += 1
ptr += 1
if left_align and width > i:
pad_count = width - i
while pad_count > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += 1
pad_count -= 1
elif c.Deref(fmt) == 98:
if is_long or is_long_long or is_size:
u_num_l: t.CUInt64T = va_arg(ap, t.CUInt64T)
else:
u_num_l: t.CUInt64T = t.CUInt64T(t.CUnsignedInt(va_arg(ap)))
if is_char:
u_num_l = t.CUInt64T(t.CChar(u_num_l))
elif is_short:
u_num_l = t.CUInt64T(t.CShort(u_num_l))
i = 0
if u_num_l == 0:
temp[0] = 48
i = 1
else:
while True:
if i >= TEMP_BUF_SIZE - 1: break
temp[i] = t.CChar(u_num_l % 2 + 48)
i += 1
u_num_l //= 2
if u_num_l <= 0: break
if alt_form and i < TEMP_BUF_SIZE - 1:
temp[i] = 98
i += 1
if not left_align and not pad_zero and width > i:
pad_count = width - i
while pad_count > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += 1
pad_count -= 1
if pad_zero and width > i:
pad_count = width - i
while pad_count > 0 and write_count < size - 1:
ptr[0] = 48
write_count += 1
ptr += 1
pad_count -= 1
while i > 0 and write_count < size - 1:
i -= 1
ptr[0] = temp[i]
write_count += 1
ptr += 1
if left_align and width > i:
pad_count = width - i
while pad_count > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += 1
pad_count -= 1
elif c.Deref(fmt) == 112:
ptr_val: t.CUInt64T = t.CUInt64T(va_arg(ap, t.CPtr))
if ptr_val == 0:
temp[0] = 40
temp[1] = 110
temp[2] = 105
temp[3] = 108
temp[4] = 41
i = 5
else:
u_num_l = ptr_val
i = 0
while True:
if i >= TEMP_BUF_SIZE - 1: break
digit = t.CInt(u_num_l % 16)
if digit < 10:
temp[i] = t.CChar(digit + 48)
else:
temp[i] = t.CChar(digit - 10 + 97)
u_num_l //= 16
i += 1
if u_num_l <= 0: break
if i < TEMP_BUF_SIZE - 1:
temp[i] = 120
i += 1
if i < TEMP_BUF_SIZE - 1:
temp[i] = 48
i += 1
if not left_align and not pad_zero and width > i:
pad_count = width - i
while pad_count > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += 1
pad_count -= 1
if pad_zero and width > i:
pad_count = width - i
while pad_count > 0 and write_count < size - 1:
ptr[0] = 48
write_count += 1
ptr += 1
pad_count -= 1
while i > 0 and write_count < size - 1:
i -= 1
ptr[0] = temp[i]
write_count += 1
ptr += 1
if left_align and width > i:
pad_count = width - i
while pad_count > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += 1
pad_count -= 1
elif c.Deref(fmt) == 102 or c.Deref(fmt) == 70:
f_upper: t.CInt = 1 if c.Deref(fmt) == 70 else 0
if precision < 0: precision = 6
fv: t.CDouble = va_arg(ap, t.CDouble)
f_sp: t.CInt = _check_special_float(fv)
if f_sp != 0:
f_sgn_len: t.CInt = 0
if f_sp == 2:
f_sgn_len = 1
elif f_sp == 1 and show_sign:
f_sgn_len = 1
elif f_sp == 1 and space_sign:
f_sgn_len = 1
f_total_len: t.CInt = f_sgn_len + 3
if not left_align and width > f_total_len:
f_pad: t.CInt = width - f_total_len
while f_pad > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += 1
f_pad -= 1
if f_sp == 2:
if write_count < size - 1:
ptr[0] = 45
write_count += 1
ptr += 1
elif f_sp == 1 and show_sign:
if write_count < size - 1:
ptr[0] = 43
write_count += 1
ptr += 1
elif f_sp == 1 and space_sign:
if write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += 1
fi_c: t.CInt = 0
while fi_c < 3 and write_count < size - 1:
fc: t.CInt = 0
if f_sp == 3:
# nan
if fi_c == 0:
fc = 110
elif fi_c == 1:
fc = 97
else:
fc = 110
else:
# inf (f_sp==1 +inf 或 f_sp==2 -inf)
if fi_c == 0:
fc = 105
elif fi_c == 1:
fc = 110
else:
fc = 102
if f_upper and fc >= 97 and fc <= 122:
fc -= 32
ptr[0] = t.CChar(fc)
write_count += 1
ptr += 1
fi_c += 1
if left_align and width > f_total_len:
f_pad = width - f_total_len
while f_pad > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += 1
f_pad -= 1
fmt += 1
continue
if fv < 0.0:
if write_count < size - 1:
ptr[0] = 45
write_count += 1
ptr += 1
fv = 0.0 - fv
elif show_sign:
if write_count < size - 1:
ptr[0] = 43
write_count += 1
ptr += 1
elif space_sign:
if write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += 1
di: t.CInt = 0
work: t.CDouble = fv
if work < 1.0:
temp[0] = 48
di = 1
else:
scale: t.CDouble = 1.0
while work >= scale * 10.0:
scale *= 10.0
while scale >= 1.0 and di < TEMP_BUF_SIZE - 1:
d: t.CInt = t.CInt(work / scale)
if d > 9: d = 9
temp[di] = t.CChar(d + 48)
di += 1
work = work - t.CDouble(d) * scale
scale /= 10.0
frac_val: t.CDouble = work
p: t.CInt = 0
while p < precision:
frac_val *= 10.0
p += 1
frac_part: t.CUInt64T = t.CUInt64T(frac_val + 0.5)
f_total: t.CInt = di + (precision + 1 if precision > 0 else 0)
if not left_align and not pad_zero and width > f_total:
pad_count = width - f_total
while pad_count > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += 1
pad_count -= 1
if pad_zero and width > f_total:
pad_count = width - f_total
while pad_count > 0 and write_count < size - 1:
ptr[0] = 48
write_count += 1
ptr += 1
pad_count -= 1
while di > 0 and write_count < size - 1:
di -= 1
ptr[0] = temp[di]
write_count += 1
ptr += 1
if precision > 0:
if write_count < size - 1:
ptr[0] = 46
write_count += 1
ptr += 1
fi: t.CInt = 0
while fi < precision and fi < TEMP_BUF_SIZE - 1:
temp[fi] = t.CChar(frac_part % 10 + 48)
fi += 1
frac_part //= 10
while fi < precision:
temp[fi] = 48
fi += 1
while fi > 0 and write_count < size - 1:
fi -= 1
ptr[0] = temp[fi]
write_count += 1
ptr += 1
elif alt_form:
if write_count < size - 1:
ptr[0] = 46
write_count += 1
ptr += 1
if left_align and width > f_total:
pad_count = width - f_total
while pad_count > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += 1
pad_count -= 1
elif c.Deref(fmt) == 101 or c.Deref(fmt) == 69:
if precision < 0: precision = 6
fv: t.CDouble = va_arg(ap, t.CDouble)
e_upper: t.CInt = 1 if c.Deref(fmt) == 69 else 0
e_sp: t.CInt = _check_special_float(fv)
if e_sp != 0:
e_sgn_len: t.CInt = 0
if e_sp == 2:
e_sgn_len = 1
elif e_sp == 1 and show_sign:
e_sgn_len = 1
elif e_sp == 1 and space_sign:
e_sgn_len = 1
e_total_len: t.CInt = e_sgn_len + 3
if not left_align and width > e_total_len:
e_pad: t.CInt = width - e_total_len
while e_pad > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += 1
e_pad -= 1
if e_sp == 2:
if write_count < size - 1:
ptr[0] = 45
write_count += 1
ptr += 1
elif e_sp == 1 and show_sign:
if write_count < size - 1:
ptr[0] = 43
write_count += 1
ptr += 1
elif e_sp == 1 and space_sign:
if write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += 1
ei_c: t.CInt = 0
while ei_c < 3 and write_count < size - 1:
ec: t.CInt = 0
if e_sp == 3:
# nan
if ei_c == 0:
ec = 110
elif ei_c == 1:
ec = 97
else:
ec = 110
else:
# inf (e_sp==1 +inf 或 e_sp==2 -inf)
if ei_c == 0:
ec = 105
elif ei_c == 1:
ec = 110
else:
ec = 102
if e_upper and ec >= 97 and ec <= 122:
ec -= 32
ptr[0] = t.CChar(ec)
write_count += 1
ptr += 1
ei_c += 1
if left_align and width > e_total_len:
e_pad = width - e_total_len
while e_pad > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += 1
e_pad -= 1
fmt += 1
continue
if fv < 0.0:
if write_count < size - 1:
ptr[0] = 45
write_count += 1
ptr += 1
fv = 0.0 - fv
elif show_sign:
if write_count < size - 1:
ptr[0] = 43
write_count += 1
ptr += 1
elif space_sign:
if write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += 1
exp10: t.CInt = 0
if fv != 0.0:
while fv >= 10.0:
fv /= 10.0
exp10 += 1
while fv < 1.0:
fv *= 10.0
exp10 -= 1
int_digit: t.CInt = t.CInt(fv)
if int_digit > 9: int_digit = 9
if int_digit < 0: int_digit = 0
frac_v: t.CDouble = fv - t.CDouble(int_digit)
p: t.CInt = 0
while p < precision:
frac_v *= 10.0
p += 1
frac_p: t.CUInt64T = t.CUInt64T(frac_v + 0.5)
carry: t.CUInt64T = 1
p = 0
while p < precision:
carry *= 10
p += 1
if frac_p >= carry and carry > 0:
frac_p = 0
int_digit += 1
if int_digit > 9:
int_digit = 1
exp10 += 1
e_total: t.CInt = 1 + (precision + 1 if precision > 0 else 0) + 4
if not left_align and not pad_zero and width > e_total:
pad_count = width - e_total
while pad_count > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += 1
pad_count -= 1
if pad_zero and width > e_total:
pad_count = width - e_total
while pad_count > 0 and write_count < size - 1:
ptr[0] = 48
write_count += 1
ptr += 1
pad_count -= 1
if write_count < size - 1:
ptr[0] = t.CChar(int_digit + 48)
write_count += 1
ptr += 1
if precision > 0:
if write_count < size - 1:
ptr[0] = 46
write_count += 1
ptr += 1
fi: t.CInt = 0
while fi < precision and fi < TEMP_BUF_SIZE - 1:
temp[fi] = t.CChar(frac_p % 10 + 48)
fi += 1
frac_p //= 10
while fi < precision:
temp[fi] = 48
fi += 1
while fi > 0 and write_count < size - 1:
fi -= 1
ptr[0] = temp[fi]
write_count += 1
ptr += 1
elif alt_form:
if write_count < size - 1:
ptr[0] = 46
write_count += 1
ptr += 1
if write_count < size - 1:
ptr[0] = 101 if e_upper == 0 else 69
write_count += 1
ptr += 1
if write_count < size - 1:
ptr[0] = 45 if exp10 < 0 else 43
write_count += 1
ptr += 1
exp_abs: t.CUInt64T = t.CUInt64T(exp10) if exp10 >= 0 else t.CUInt64T(0 - exp10)
ei: t.CInt = 0
if exp_abs == 0:
temp[0] = 48
temp[1] = 48
ei = 2
else:
while exp_abs > 0 and ei < TEMP_BUF_SIZE - 1:
temp[ei] = t.CChar(exp_abs % 10 + 48)
ei += 1
exp_abs //= 10
while ei < 2:
temp[ei] = 48
ei += 1
while ei > 0 and write_count < size - 1:
ei -= 1
ptr[0] = temp[ei]
write_count += 1
ptr += 1
if left_align and width > e_total:
pad_count = width - e_total
while pad_count > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += 1
pad_count -= 1
elif c.Deref(fmt) == 103 or c.Deref(fmt) == 71:
if precision < 0: precision = 6
if precision == 0: precision = 1
fv: t.CDouble = va_arg(ap, t.CDouble)
g_upper: t.CInt = 1 if c.Deref(fmt) == 71 else 0
g_sp: t.CInt = _check_special_float(fv)
if g_sp != 0:
g_sgn_len: t.CInt = 0
if g_sp == 2:
g_sgn_len = 1
elif g_sp == 1 and show_sign:
g_sgn_len = 1
elif g_sp == 1 and space_sign:
g_sgn_len = 1
g_total_len: t.CInt = g_sgn_len + 3
if not left_align and width > g_total_len:
g_pad: t.CInt = width - g_total_len
while g_pad > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += 1
g_pad -= 1
if g_sp == 2:
if write_count < size - 1:
ptr[0] = 45
write_count += 1
ptr += 1
elif g_sp == 1 and show_sign:
if write_count < size - 1:
ptr[0] = 43
write_count += 1
ptr += 1
elif g_sp == 1 and space_sign:
if write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += 1
gi_c: t.CInt = 0
while gi_c < 3 and write_count < size - 1:
gc: t.CInt = 0
if g_sp == 3:
# nan
if gi_c == 0:
gc = 110
elif gi_c == 1:
gc = 97
else:
gc = 110
else:
# inf (g_sp==1 +inf 或 g_sp==2 -inf)
if gi_c == 0:
gc = 105
elif gi_c == 1:
gc = 110
else:
gc = 102
if g_upper and gc >= 97 and gc <= 122:
gc -= 32
ptr[0] = t.CChar(gc)
write_count += 1
ptr += 1
gi_c += 1
if left_align and width > g_total_len:
g_pad = width - g_total_len
while g_pad > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += 1
g_pad -= 1
fmt += 1
continue
if fv < 0.0:
if write_count < size - 1:
ptr[0] = 45
write_count += 1
ptr += 1
fv = 0.0 - fv
elif show_sign:
if write_count < size - 1:
ptr[0] = 43
write_count += 1
ptr += 1
elif space_sign:
if write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += 1
fv_orig: t.CDouble = fv
exp10: t.CInt = 0
if fv != 0.0:
while fv >= 10.0:
fv /= 10.0
exp10 += 1
while fv < 1.0:
fv *= 10.0
exp10 -= 1
g_use_e: t.CInt = 0
if exp10 < -4 or exp10 >= precision:
g_use_e = 1
g_len: t.CInt = 0
if g_use_e:
int_digit: t.CInt = t.CInt(fv)
if int_digit > 9: int_digit = 9
if int_digit < 0: int_digit = 0
frac_v: t.CDouble = fv - t.CDouble(int_digit)
prec_e: t.CInt = precision - 1
p: t.CInt = 0
while p < prec_e:
frac_v *= 10.0
p += 1
frac_p: t.CUInt64T = t.CUInt64T(frac_v + 0.5)
carry: t.CUInt64T = 1
p = 0
while p < prec_e:
carry *= 10
p += 1
if frac_p >= carry and carry > 0:
frac_p = 0
int_digit += 1
if int_digit > 9:
int_digit = 1
exp10 += 1
temp[0] = t.CChar(int_digit + 48)
g_len = 1
if prec_e > 0:
temp[1] = 46
g_len = 2
fi: t.CInt = 0
while fi < prec_e and g_len < TEMP_BUF_SIZE - 1:
temp[g_len] = t.CChar(frac_p % 10 + 48)
g_len += 1
frac_p //= 10
lo: t.CInt = 2
hi: t.CInt = g_len - 1
while lo < hi:
tc: t.CChar = temp[lo]
temp[lo] = temp[hi]
temp[hi] = tc
lo += 1
hi -= 1
else:
prec_f: t.CInt = precision - 1 - exp10
if prec_f < 0: prec_f = 0
work: t.CDouble = fv_orig
if work < 1.0:
temp[0] = 48
g_len = 1
else:
scale: t.CDouble = 1.0
while work >= scale * 10.0:
scale *= 10.0
while scale >= 1.0 and g_len < TEMP_BUF_SIZE - 1:
d: t.CInt = t.CInt(work / scale)
if d > 9: d = 9
temp[g_len] = t.CChar(d + 48)
g_len += 1
work = work - t.CDouble(d) * scale
scale /= 10.0
if prec_f > 0 and g_len < TEMP_BUF_SIZE - 1:
temp[g_len] = 46
g_len += 1
frac_val: t.CDouble = work
p = 0
while p < prec_f:
frac_val *= 10.0
p += 1
frac_part: t.CUInt64T = t.CUInt64T(frac_val + 0.5)
fi = 0
while fi < prec_f and g_len < TEMP_BUF_SIZE - 1:
temp[g_len] = t.CChar(frac_part % 10 + 48)
g_len += 1
frac_part //= 10
lo = g_len - prec_f
hi = g_len - 1
while lo < hi:
tc = temp[lo]
temp[lo] = temp[hi]
temp[hi] = tc
lo += 1
hi -= 1
if not alt_form and g_len > 0:
while g_len > 0:
if temp[g_len - 1] == 48:
g_len -= 1
else:
break
if g_len > 0 and temp[g_len - 1] == 46:
g_len -= 1
g_total: t.CInt = g_len
if g_use_e: g_total = g_len + 4
if not left_align and not pad_zero and width > g_total:
pad_count = width - g_total
while pad_count > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += 1
pad_count -= 1
if pad_zero and width > g_total:
pad_count = width - g_total
while pad_count > 0 and write_count < size - 1:
ptr[0] = 48
write_count += 1
ptr += 1
pad_count -= 1
gi: t.CInt = 0
while gi < g_len and write_count < size - 1:
ptr[0] = temp[gi]
write_count += 1
ptr += 1
gi += 1
if g_use_e:
if write_count < size - 1:
ptr[0] = 101 if g_upper == 0 else 69
write_count += 1
ptr += 1
if write_count < size - 1:
ptr[0] = 45 if exp10 < 0 else 43
write_count += 1
ptr += 1
exp_abs: t.CUInt64T = t.CUInt64T(exp10) if exp10 >= 0 else t.CUInt64T(0 - exp10)
ei: t.CInt = 0
if exp_abs == 0:
temp[0] = 48
temp[1] = 48
ei = 2
else:
while exp_abs > 0 and ei < TEMP_BUF_SIZE - 1:
temp[ei] = t.CChar(exp_abs % 10 + 48)
ei += 1
exp_abs //= 10
while ei < 2:
temp[ei] = 48
ei += 1
while ei > 0 and write_count < size - 1:
ei -= 1
ptr[0] = temp[ei]
write_count += 1
ptr += 1
if left_align and width > g_total:
pad_count = width - g_total
while pad_count > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += 1
pad_count -= 1
elif c.Deref(fmt) == 97 or c.Deref(fmt) == 65:
a_upper: t.CInt = 1 if c.Deref(fmt) == 65 else 0
fv: t.CDouble = va_arg(ap, t.CDouble)
a_sp: t.CInt = _check_special_float(fv)
if a_sp != 0:
a_sgn_len: t.CInt = 0
if a_sp == 2:
a_sgn_len = 1
elif a_sp == 1 and show_sign:
a_sgn_len = 1
elif a_sp == 1 and space_sign:
a_sgn_len = 1
a_total_len: t.CInt = a_sgn_len + 3
if not left_align and width > a_total_len:
a_pad: t.CInt = width - a_total_len
while a_pad > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += 1
a_pad -= 1
if a_sp == 2:
if write_count < size - 1:
ptr[0] = 45
write_count += 1
ptr += 1
elif a_sp == 1 and show_sign:
if write_count < size - 1:
ptr[0] = 43
write_count += 1
ptr += 1
elif a_sp == 1 and space_sign:
if write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += 1
ai_c: t.CInt = 0
while ai_c < 3 and write_count < size - 1:
ac: t.CInt = 0
if a_sp == 3:
# nan
if ai_c == 0:
ac = 110
elif ai_c == 1:
ac = 97
else:
ac = 110
else:
# inf (a_sp==1 +inf 或 a_sp==2 -inf)
if ai_c == 0:
ac = 105
elif ai_c == 1:
ac = 110
else:
ac = 102
if a_upper and ac >= 97 and ac <= 122:
ac -= 32
ptr[0] = t.CChar(ac)
write_count += 1
ptr += 1
ai_c += 1
if left_align and width > a_total_len:
a_pad = width - a_total_len
while a_pad > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += 1
a_pad -= 1
fmt += 1
continue
fbits: t.CUInt64T = 0
c.Load(c.Addr(fbits), c.Addr(fv))
a_neg: t.CInt = 1 if (fbits >> 63) != 0 else 0
a_exp: t.CInt = t.CInt((fbits >> 52) & 0x7FF)
a_frac: t.CUInt64T = fbits & 0x000FFFFFFFFFFFFF
a_leading: t.CInt = 0
a_binexp: t.CInt = 0
if a_exp == 0:
a_leading = 0
if a_frac == 0:
a_binexp = 0
else:
a_binexp = -1022
else:
a_leading = 1
a_binexp = a_exp - 1023
a_prec: t.CInt = precision
if a_prec < 0:
a_prec = 13
if a_prec > 50:
a_prec = 50
a_hi: t.CInt = 0
while a_hi < 13 and a_hi < a_prec:
a_digit: t.CInt = t.CInt((a_frac >> (48 - 4 * a_hi)) & 0xF)
if a_digit < 10:
temp[a_hi] = t.CChar(a_digit + 48)
else:
if a_upper:
temp[a_hi] = t.CChar(a_digit - 10 + 65)
else:
temp[a_hi] = t.CChar(a_digit - 10 + 97)
a_hi += 1
while a_hi < a_prec:
temp[a_hi] = 48
a_hi += 1
a_hd_count: t.CInt = a_prec
if precision < 0:
while a_hd_count > 0 and temp[a_hd_count - 1] == 48:
a_hd_count -= 1
a_has_dot: t.CInt = 0
if a_hd_count > 0:
a_has_dot = 1
elif alt_form:
a_has_dot = 1
a_eb: t.CInt = a_binexp
a_esign: t.CInt = 0
if a_binexp < 0:
a_esign = 1
a_eb = -a_binexp
a_ei: t.CInt = 0
if a_eb == 0:
temp[60] = 48
a_ei = 1
else:
while a_eb > 0 and a_ei < 7:
temp[60 + a_ei] = t.CChar(a_eb % 10 + 48)
a_ei += 1
a_eb //= 10
a_ecount: t.CInt = a_ei
a_sign_len: t.CInt = 0
if a_neg:
a_sign_len = 1
elif show_sign:
a_sign_len = 1
elif space_sign:
a_sign_len = 1
a_content_len: t.CInt = a_sign_len + 2 + 1 + a_has_dot + a_hd_count + 1 + 1 + a_ecount
if not left_align and not pad_zero and width > a_content_len:
a_pad = width - a_content_len
while a_pad > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += 1
a_pad -= 1
if a_neg:
if write_count < size - 1:
ptr[0] = 45
write_count += 1
ptr += 1
elif show_sign:
if write_count < size - 1:
ptr[0] = 43
write_count += 1
ptr += 1
elif space_sign:
if write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += 1
if pad_zero and width > a_content_len:
a_pad = width - a_content_len
while a_pad > 0 and write_count < size - 1:
ptr[0] = 48
write_count += 1
ptr += 1
a_pad -= 1
if write_count < size - 1:
ptr[0] = 48
write_count += 1
ptr += 1
if write_count < size - 1:
if a_upper:
ptr[0] = 88
else:
ptr[0] = 120
write_count += 1
ptr += 1
if write_count < size - 1:
ptr[0] = t.CChar(a_leading + 48)
write_count += 1
ptr += 1
if a_has_dot:
if write_count < size - 1:
ptr[0] = 46
write_count += 1
ptr += 1
a_hj: t.CInt = 0
while a_hj < a_hd_count and write_count < size - 1:
ptr[0] = temp[a_hj]
write_count += 1
ptr += 1
a_hj += 1
if write_count < size - 1:
if a_upper:
ptr[0] = 80
else:
ptr[0] = 112
write_count += 1
ptr += 1
if write_count < size - 1:
if a_esign:
ptr[0] = 45
else:
ptr[0] = 43
write_count += 1
ptr += 1
a_ek: t.CInt = a_ecount
while a_ek > 0 and write_count < size - 1:
a_ek -= 1
ptr[0] = temp[60 + a_ek]
write_count += 1
ptr += 1
if left_align and width > a_content_len:
a_pad = width - a_content_len
while a_pad > 0 and write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += 1
a_pad -= 1
elif c.Deref(fmt) == 110:
if is_long_long or is_long:
np: t.CInt64T | t.CPtr = va_arg(ap, t.CInt64T | t.CPtr)
if np != None:
np[0] = t.CInt64T(write_count)
elif is_short:
sp: t.CShort | t.CPtr = va_arg(ap, t.CShort | t.CPtr)
if sp != None:
sp[0] = t.CShort(write_count)
elif is_char:
cp: t.CChar | t.CPtr = va_arg(ap, t.CChar | t.CPtr)
if cp != None:
cp[0] = t.CChar(write_count)
else:
ip: t.CInt | t.CPtr = va_arg(ap, t.CInt | t.CPtr)
if ip != None:
ip[0] = write_count
elif c.Deref(fmt) == 37:
if write_count < size - 1:
ptr[0] = 37
write_count += 1
ptr += 1
else:
if write_count < size - 1:
ptr[0] = c.Deref(fmt)
write_count += 1
ptr += 1
fmt += 1
ptr[0] = 0
return write_count