import t, c import viperio from stdarg import arg TEMP_BUF_SIZE: t.CDefine = 24 def get_digit_count(num: t.CUnsignedInt, base: t.CInt) -> t.CStatic | t.CInt | t.State: 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.State: if buf == None or rule == None: return snprintf(buf, 0, rule, 0) def vsprintf(buf: t.CChar | t.CPtr, rule: str, *args) -> t.CInt | t.State: if buf == None or rule == None: return 0 return snprintf(buf, 0, rule, 0) def snprintf(buf: t.CChar | t.CPtr, size: t.CSizeT, fmt: str, *args) -> t.CInt | t.State: if buf == None or fmt == None or size == 0: return 0 ptr: t.CChar | t.CPtr = buf write_count: t.CInt = 0 temp: list[t.CChar, 24] 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 precision: t.CInt = -1 is_long: t.CInt = 0 is_long_long: t.CInt = 0 is_size: 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 else: break 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) == 122: is_size = 1 fmt += 1 if c.Deref(fmt) == 99: if write_count < size - 1: ptr_i: t.CInt = arg() ptr[0] = t.CChar(ptr_i) write_count += 1 ptr += 1 else: ptr_i: t.CInt = arg() elif c.Deref(fmt) == 115: s: str = arg() if s == 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: if is_long or is_long_long or is_size: num: t.CInt = t.CInt(arg()) else: num: t.CInt = arg() sign: t.CInt = 0 if num < 0: sign = 1 if num == -2147483648: u_num: t.CUnsignedInt = 2147483648 else: u_num: t.CUnsignedInt = t.CUnsignedInt(-num) else: u_num: t.CUnsignedInt = t.CUnsignedInt(num) if show_sign: sign = 2 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 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 = arg(t.CUInt64T) else: u_num_l: t.CUInt64T = t.CUInt64T(t.CUnsignedInt(arg())) 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 = arg(t.CUInt64T) else: u_num_l: t.CUInt64T = t.CUInt64T(t.CUnsignedInt(arg())) 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 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) == 88: if is_long or is_long_long or is_size: u_num_l: t.CUInt64T = arg() else: u_num_l: t.CUInt64T = t.CUInt64T(t.CUnsignedInt(arg())) 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 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: if precision < 0: precision = 6 fv: float = arg() 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 di: t.CInt = 0 int_part: t.CUnsignedLong = t.CUnsignedLong(t.CLongLong(fv)) frac_val: float = fv - float(int_part) p: t.CInt = 0 while p < precision: frac_val *= 10.0 p += 1 frac_part: t.CUnsignedLong = t.CUnsignedLong(frac_val + 0.5) if int_part == 0: temp[0] = 48 di = 1 else: while int_part > 0 and di < TEMP_BUF_SIZE - 1: temp[di] = t.CChar(int_part % 10 + 48) di += 1 int_part //= 10 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 > 0 and write_count < size - 1: fi -= 1 ptr[0] = temp[fi] 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) == 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