Files
TransPyC/includes/viperlib.vp

1377 lines
56 KiB
Plaintext
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 fmt is None: return 0
if buf is None or size == 0:
return vsnprintf(None, 0, fmt, args)
return vsnprintf(buf, size, fmt, args)
# Check floating-point special values (IEEE 754)
# Return: 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 fmt is None: return 0
# 长度探测模式buf is None 时只计算格式化后长度,不实际写入
# _step=0 使 ptr 不前进,反复写入同一个 dummy 字节无害write_count 正确累加
count_mode: t.CInt = 0
_step: t.CInt = 1
_dummy: t.CChar = '\0'
if buf is None or size == 0:
count_mode = 1
_step = 0
buf = c.Addr(_dummy)
size = 0x7FFFFFFF
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 += _step
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 += _step
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 += _step
pad_count -= 1
while c.Deref(s) != 0 and write_count < size - 1:
ptr[0] = c.Deref(s)
write_count += 1
ptr += _step
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 += _step
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 += _step
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 += _step
pad_count -= 1
while i > 0 and write_count < size - 1:
i -= 1
ptr[0] = temp[i]
write_count += 1
ptr += _step
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 += _step
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 += _step
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 += _step
pad_count -= 1
while i > 0 and write_count < size - 1:
i -= 1
ptr[0] = temp[i]
write_count += 1
ptr += _step
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 += _step
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 += _step
pad_count -= 1
if prefix_len > 0:
if write_count < size - 1:
ptr[0] = 48
write_count += 1
ptr += _step
if write_count < size - 1:
ptr[0] = 120
write_count += 1
ptr += _step
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 += _step
pad_count -= 1
while i > 0 and write_count < size - 1:
i -= 1
ptr[0] = temp[i]
write_count += 1
ptr += _step
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 += _step
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 += _step
pad_count -= 1
if prefix_len > 0:
if write_count < size - 1:
ptr[0] = 48
write_count += 1
ptr += _step
if write_count < size - 1:
ptr[0] = 88
write_count += 1
ptr += _step
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 += _step
pad_count -= 1
while i > 0 and write_count < size - 1:
i -= 1
ptr[0] = temp[i]
write_count += 1
ptr += _step
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 += _step
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 += _step
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 += _step
pad_count -= 1
while i > 0 and write_count < size - 1:
i -= 1
ptr[0] = temp[i]
write_count += 1
ptr += _step
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 += _step
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 += _step
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 += _step
pad_count -= 1
while i > 0 and write_count < size - 1:
i -= 1
ptr[0] = temp[i]
write_count += 1
ptr += _step
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 += _step
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 += _step
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 += _step
pad_count -= 1
while i > 0 and write_count < size - 1:
i -= 1
ptr[0] = temp[i]
write_count += 1
ptr += _step
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 += _step
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 += _step
f_pad -= 1
if f_sp == 2:
if write_count < size - 1:
ptr[0] = 45
write_count += 1
ptr += _step
elif f_sp == 1 and show_sign:
if write_count < size - 1:
ptr[0] = 43
write_count += 1
ptr += _step
elif f_sp == 1 and space_sign:
if write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += _step
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 += _step
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 += _step
f_pad -= 1
fmt += 1
continue
if fv < 0.0:
if write_count < size - 1:
ptr[0] = 45
write_count += 1
ptr += _step
fv = 0.0 - fv
elif show_sign:
if write_count < size - 1:
ptr[0] = 43
write_count += 1
ptr += _step
elif space_sign:
if write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += _step
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 += _step
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 += _step
pad_count -= 1
while di > 0 and write_count < size - 1:
di -= 1
ptr[0] = temp[di]
write_count += 1
ptr += _step
if precision > 0:
if write_count < size - 1:
ptr[0] = 46
write_count += 1
ptr += _step
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 += _step
elif alt_form:
if write_count < size - 1:
ptr[0] = 46
write_count += 1
ptr += _step
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 += _step
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 += _step
e_pad -= 1
if e_sp == 2:
if write_count < size - 1:
ptr[0] = 45
write_count += 1
ptr += _step
elif e_sp == 1 and show_sign:
if write_count < size - 1:
ptr[0] = 43
write_count += 1
ptr += _step
elif e_sp == 1 and space_sign:
if write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += _step
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 += _step
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 += _step
e_pad -= 1
fmt += 1
continue
if fv < 0.0:
if write_count < size - 1:
ptr[0] = 45
write_count += 1
ptr += _step
fv = 0.0 - fv
elif show_sign:
if write_count < size - 1:
ptr[0] = 43
write_count += 1
ptr += _step
elif space_sign:
if write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += _step
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 += _step
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 += _step
pad_count -= 1
if write_count < size - 1:
ptr[0] = t.CChar(int_digit + 48)
write_count += 1
ptr += _step
if precision > 0:
if write_count < size - 1:
ptr[0] = 46
write_count += 1
ptr += _step
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 += _step
elif alt_form:
if write_count < size - 1:
ptr[0] = 46
write_count += 1
ptr += _step
if write_count < size - 1:
ptr[0] = 101 if e_upper == 0 else 69
write_count += 1
ptr += _step
if write_count < size - 1:
ptr[0] = 45 if exp10 < 0 else 43
write_count += 1
ptr += _step
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 += _step
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 += _step
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 += _step
g_pad -= 1
if g_sp == 2:
if write_count < size - 1:
ptr[0] = 45
write_count += 1
ptr += _step
elif g_sp == 1 and show_sign:
if write_count < size - 1:
ptr[0] = 43
write_count += 1
ptr += _step
elif g_sp == 1 and space_sign:
if write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += _step
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 += _step
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 += _step
g_pad -= 1
fmt += 1
continue
if fv < 0.0:
if write_count < size - 1:
ptr[0] = 45
write_count += 1
ptr += _step
fv = 0.0 - fv
elif show_sign:
if write_count < size - 1:
ptr[0] = 43
write_count += 1
ptr += _step
elif space_sign:
if write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += _step
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 += _step
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 += _step
pad_count -= 1
gi: t.CInt = 0
while gi < g_len and write_count < size - 1:
ptr[0] = temp[gi]
write_count += 1
ptr += _step
gi += 1
if g_use_e:
if write_count < size - 1:
ptr[0] = 101 if g_upper == 0 else 69
write_count += 1
ptr += _step
if write_count < size - 1:
ptr[0] = 45 if exp10 < 0 else 43
write_count += 1
ptr += _step
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 += _step
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 += _step
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 += _step
a_pad -= 1
if a_sp == 2:
if write_count < size - 1:
ptr[0] = 45
write_count += 1
ptr += _step
elif a_sp == 1 and show_sign:
if write_count < size - 1:
ptr[0] = 43
write_count += 1
ptr += _step
elif a_sp == 1 and space_sign:
if write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += _step
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 += _step
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 += _step
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 += _step
a_pad -= 1
if a_neg:
if write_count < size - 1:
ptr[0] = 45
write_count += 1
ptr += _step
elif show_sign:
if write_count < size - 1:
ptr[0] = 43
write_count += 1
ptr += _step
elif space_sign:
if write_count < size - 1:
ptr[0] = 32
write_count += 1
ptr += _step
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 += _step
a_pad -= 1
if write_count < size - 1:
ptr[0] = 48
write_count += 1
ptr += _step
if write_count < size - 1:
if a_upper:
ptr[0] = 88
else:
ptr[0] = 120
write_count += 1
ptr += _step
if write_count < size - 1:
ptr[0] = t.CChar(a_leading + 48)
write_count += 1
ptr += _step
if a_has_dot:
if write_count < size - 1:
ptr[0] = 46
write_count += 1
ptr += _step
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 += _step
a_hj += 1
if write_count < size - 1:
if a_upper:
ptr[0] = 80
else:
ptr[0] = 112
write_count += 1
ptr += _step
if write_count < size - 1:
if a_esign:
ptr[0] = 45
else:
ptr[0] = 43
write_count += 1
ptr += _step
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 += _step
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 += _step
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 += _step
else:
if write_count < size - 1:
ptr[0] = c.Deref(fmt)
write_count += 1
ptr += _step
fmt += 1
ptr[0] = 0
return write_count