src/common/xqc_str.c (265 lines of code) (raw):

/** * @copyright Copyright (c) 2022, Alibaba Group Holding Limited */ #include "src/common/xqc_str.h" unsigned char * xqc_hex_dump(unsigned char *dst, const unsigned char *src, size_t len) { static const unsigned char hex[] = "0123456789abcdef"; while (len--) { *dst++ = hex[*src >> 4]; *dst++ = hex[*src++ & 0xf]; } return dst; } unsigned char * xqc_vsprintf(unsigned char *buf, unsigned char *last, const char *fmt, va_list args) { unsigned char *p; unsigned char zero; int d; double f; size_t len, slen; int64_t i64; uint64_t ui64, frac; uint64_t width, sign, hex, max_width, frac_width, scale, n; xqc_str_t *v; while (*fmt && buf < last) { if (*fmt == '%') { i64 = 0; ui64 = 0; zero = (unsigned char) ((*++fmt == '0') ? '0' : ' '); width = 0; sign = 1; hex = 0; max_width = 0; frac_width = 0; slen = (size_t) -1; while (*fmt >= '0' && *fmt <= '9') { width = width * 10 + *fmt++ - '0'; } for ( ;; ) { switch (*fmt) { case 'u': sign = 0; fmt++; continue; case 'm': max_width = 1; fmt++; continue; case 'X': hex = 2; sign = 0; fmt++; continue; case 'x': hex = 1; sign = 0; fmt++; continue; case '.': fmt++; while (*fmt >= '0' && *fmt <= '9') { frac_width = frac_width * 10 + *fmt++ - '0'; } break; case '*': slen = va_arg(args, size_t); fmt++; continue; default: break; } break; } switch (*fmt) { case 'V': v = va_arg(args, xqc_str_t *); len = xqc_min(((size_t) (last - buf)), v->len); buf = xqc_cpymem(buf, v->data, len); fmt++; continue; case 's': p = va_arg(args, unsigned char *); if (slen == (size_t) -1) { while (*p && buf < last) { *buf++ = *p++; } } else { len = xqc_min(((size_t) (last - buf)), slen); buf = xqc_cpymem(buf, p, len); } fmt++; continue; case 'O': i64 = (int64_t) va_arg(args, off_t); sign = 1; break; case 'P': i64 = (int64_t) va_arg(args, int64_t); sign = 1; break; case 'T': i64 = (int64_t) va_arg(args, time_t); sign = 1; break; case 'z': if (sign) { i64 = (int64_t) va_arg(args, ssize_t); } else { ui64 = (uint64_t) va_arg(args, size_t); } break; case 'i': if (sign) { i64 = (int64_t) va_arg(args, int64_t); } else { ui64 = (uint64_t) va_arg(args, uint64_t); } if (max_width) { width = XQC_INT_T_LEN; } break; case 'd': if (sign) { i64 = (int64_t) va_arg(args, int); } else { ui64 = (uint64_t) va_arg(args, unsigned int); } break; case 'l': if (sign) { i64 = (int64_t) va_arg(args, long); } else { ui64 = (uint64_t) va_arg(args, unsigned long); } break; case 'D': if (sign) { i64 = (int64_t) va_arg(args, int32_t); } else { ui64 = (uint64_t) va_arg(args, uint32_t); } break; case 'L': if (sign) { i64 = va_arg(args, int64_t); } else { ui64 = va_arg(args, uint64_t); } break; case 'f': f = va_arg(args, double); if (f < 0) { *buf++ = '-'; f = -f; } ui64 = (int64_t) f; frac = 0; if (frac_width) { scale = 1; for (n = frac_width; n; n--) { scale *= 10; } frac = (uint64_t) ((f - (double) ui64) * scale + 0.5); if (frac == scale) { ui64++; frac = 0; } } buf = xqc_sprintf_num(buf, last, ui64, zero, 0, width); if (frac_width) { if (buf < last) { *buf++ = '.'; } buf = xqc_sprintf_num(buf, last, frac, '0', 0, frac_width); } fmt++; continue; #ifndef XQC_SYS_WINDOWS case 'r': i64 = (int64_t) va_arg(args, rlim_t); sign = 1; break; #endif case 'p': ui64 = (uintptr_t) va_arg(args, void *); hex = 2; sign = 0; zero = '0'; width = XQC_PTR_SIZE * 2; break; case 'c': d = va_arg(args, int); *buf++ = (unsigned char) (d & 0xff); fmt++; continue; case 'Z': *buf++ = '\0'; fmt++; continue; case 'N': *buf++ = LF; fmt++; continue; case '%': *buf++ = '%'; fmt++; continue; default: *buf++ = *fmt++; continue; } if (sign) { if (i64 < 0) { *buf++ = '-'; ui64 = (uint64_t) -i64; } else { ui64 = (uint64_t) i64; } } buf = xqc_sprintf_num(buf, last, ui64, zero, hex, width); fmt++; } else { *buf++ = *fmt++; } } return buf; } unsigned char * xqc_sprintf_num(unsigned char *buf, unsigned char *last, uint64_t ui64, unsigned char zero, uintptr_t hexadecimal, uintptr_t width) { unsigned char *p, temp[XQC_INT64_LEN + 1]; /* * we need temp[XQC_INT64_LEN] only, * but icc issues the warning */ size_t len; uint32_t ui32; static const unsigned char hex[] = "0123456789abcdef"; static const unsigned char HEX[] = "0123456789ABCDEF"; p = temp + XQC_INT64_LEN; if (hexadecimal == 0) { if (ui64 <= (uint64_t) XQC_MAX_UINT32_VALUE) { ui32 = (uint32_t) ui64; do { *--p = (unsigned char) (ui32 % 10 + '0'); } while (ui32 /= 10); } else { do { *--p = (unsigned char) (ui64 % 10 + '0'); } while (ui64 /= 10); } } else if (hexadecimal == 1) { do { *--p = hex[(uint32_t) (ui64 & 0xf)]; } while (ui64 >>= 4); } else { /* hexadecimal == 2 */ do { *--p = HEX[(uint32_t) (ui64 & 0xf)]; } while (ui64 >>= 4); } /* zero or space padding */ len = (temp + XQC_INT64_LEN) - p; while (len++ < width && buf < last) { *buf++ = zero; } /* number safe copy */ len = (temp + XQC_INT64_LEN) - p; if (buf + len > last) { len = last - buf; } return xqc_cpymem(buf, p, len); }