
221220000 张三 Linux zzy 5.15.146.1-microsoft-standard-WSL2 #1 SMP Thu Jan 11 04:09:03 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux 11:57:41 up 2 days, 2:11, 1 user, load average: 0.55, 0.59, 0.46
83 lines
1.9 KiB
C
83 lines
1.9 KiB
C
#include <klib.h>
|
|
|
|
int num_to_ascii(int num, int power, int size, char *buf) {
|
|
if (size <= 1) {
|
|
return 0;
|
|
}
|
|
|
|
int ret = 0, i = 0;
|
|
char _buf[sizeof(num) * 3];
|
|
if (num == 0) {
|
|
*buf = '0';
|
|
return 1;
|
|
}
|
|
|
|
for (i = 1; num; i ++) {
|
|
_buf[i] = (num % power) < 10 ? ('0' + num % power) : ('a' + num % power);
|
|
num /= power;
|
|
}
|
|
if (i > size) {
|
|
return 0; // error buffer overflow
|
|
}
|
|
ret = i - 1;
|
|
|
|
for (i --; i > 0; i --, buf ++ ) {
|
|
*buf = _buf[i];
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
static inline int print_fmt(char **out, int n, const char** fmt, void* _ap) {
|
|
va_list ap = *(va_list*)_ap;
|
|
int ret = 0;
|
|
switch (**fmt) {
|
|
case 'd':
|
|
ret = num_to_ascii(va_arg(ap, int), 10, n, *out);
|
|
(*out) += ret;
|
|
break;
|
|
case 's':
|
|
const char* str = va_arg(ap, const char*);
|
|
if (ret > n) break;
|
|
for (; *str; str ++, (*out) ++, ret ++ ) {
|
|
if (ret >= n) {
|
|
return ret; // error buffer overflow
|
|
}
|
|
**out = *str;
|
|
}
|
|
break;
|
|
case 'c':
|
|
char ch = va_arg(ap, int);
|
|
ret = 1;
|
|
**out = ch;
|
|
(*out) ++;
|
|
break;
|
|
case 'x':
|
|
ret = num_to_ascii(va_arg(ap, int), 16, n, *out);
|
|
(*out) += ret;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
(*fmt) ++;
|
|
*(va_list*)_ap = ap;
|
|
return ret;
|
|
}
|
|
|
|
int rvsnprintf(char* out, size_t n, const char* fmt, va_list ap) {
|
|
int ret = 0;
|
|
while(*fmt && n) {
|
|
if (*fmt == '%') {
|
|
// FIXME
|
|
fmt++;
|
|
print_fmt(&out, 123, &fmt, &ap);
|
|
continue;
|
|
}
|
|
*out = *fmt;
|
|
out ++;
|
|
fmt ++;
|
|
n --;
|
|
}
|
|
*out = '\0';
|
|
return ret;
|
|
}
|