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