#include #include #include #include #include int snprintf(char * buff, size_t len, const char *format, ...) { va_list ap; va_start(ap, format); len = vsnprintf(buff, len, format, ap); va_end(ap); return len; } struct vsnprintf_s { char* buff; size_t len; size_t i; }; int vsnprintf_putc_fun(int c, void* p) { struct vsnprintf_s *s = (struct vsnprintf_s*)p; if (s->i < s->len - 1) { s->buff[s->i] = c; s->i++; return 1; } else { return 0; } } int vsnprintf(char *buff, size_t len, const char* format, va_list arg){ if (!buff || !format) return -1; struct vsnprintf_s s; s.buff = buff; s.len = len; s.i = 0; size_t ret = vcprintf(vsnprintf_putc_fun, &s, format, arg); ASSERT(ret == s.i); buff[s.i] = 0; return s.i; } int vcprintf(int (*putc_fun)(int c, void* p), void* p, const char* format, va_list ap) { if (!format) return -1; int ret = 0; #define PUTCHAR(thechar) { int _tmp = putc_fun(thechar, p);\ if (_tmp == 1) ret++; \ else if (_tmp == 0) return ret; \ else if (_tmp < 0) return _tmp; } size_t i; for(i = 0; format[i] != '\0' ; i++) { if (format[i] == '%') { i++; int na = -1; int nb = -1; int u = 0; int l = 0; bool dotspec = false; bool spec = true; while (spec) { if (format[i] == 'l') { l++; i++; } else if (format[i] == 'u') { u = 1; i++; } else if (isdigit(format[i])) { if (dotspec) { if (nb == -1) nb = 0; nb = nb * 10 + (format[i] - '0'); } else { if (na == -1) na = 0; na = na * 10 + (format[i] - '0'); } i++; } else if (format[i] == '.') { dotspec = true; i++; } else { spec = false; } } if (format[i] == '%') { PUTCHAR('%'); } else if (format[i] == 'i' || format[i] == 'd') { if (u) { // TODO } else { long long int integer; if (l == 0) integer = va_arg(ap, int); if (l == 1) integer = va_arg(ap, long int); if (l == 2) integer = va_arg(ap, long long int); int cpt2 = 0; char buff_int[32]; if (integer<0) { PUTCHAR('-'); } do { int m10 = integer%10; m10 = (m10 < 0)? -m10:m10; buff_int[cpt2++] = (char)('0'+ m10); integer = integer/10; } while(integer != 0); for(cpt2 = cpt2 - 1; cpt2 >= 0; cpt2--) PUTCHAR(buff_int[cpt2]); } } else if (format[i] == 'c') { int value = va_arg(ap,int); PUTCHAR((char)value); break; } else if (format[i] == 's') { char *string = va_arg(ap,char *); if (!string) string = "(null)"; for(; *string != '\0' ; string++) PUTCHAR(*string); } else if (format[i] == 'x') { unsigned long long int hexa; if (l == 0) hexa = va_arg(ap, unsigned int); if (l == 1) hexa = va_arg(ap, unsigned long int); if (l == 2) hexa = va_arg(ap, unsigned long long int); int had_nonzero = 0; for(int j = 0; j < 8; j++) { unsigned int nb = (unsigned int)(hexa << (j*4)); nb = (nb >> 28) & 0xf; // Skip the leading zeros if (nb == 0) { if (had_nonzero) { PUTCHAR('0'); } } else { had_nonzero = 1; if (nb < 10) { PUTCHAR('0'+nb); } else { PUTCHAR('a'+(nb-10)); } } } if (!had_nonzero) { PUTCHAR('0'); } } else if (format[i] == 'p') { unsigned int hexa = va_arg(ap,int); for (int j = 0; j < 8; j++) { unsigned int nb = (unsigned int)(hexa << (j*4)); nb = (nb >> 28) & 0xf; if (nb < 10) { PUTCHAR('0'+nb); } else { PUTCHAR('a'+(nb-10)); } } } else { PUTCHAR('%'); PUTCHAR(format[i]); } } else { PUTCHAR(format[i]); } } return ret; } /* vim: set ts=4 sw=4 tw=0 noet :*/