vsnprintf.c 973 B

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. #include "stdio_impl.h"
  2. #include <limits.h>
  3. #include <string.h>
  4. #include <errno.h>
  5. #include <stdint.h>
  6. struct cookie {
  7. char *s;
  8. size_t n;
  9. };
  10. #define MIN(a, b) ((a) < (b) ? (a) : (b))
  11. static size_t sn_write(FILE *f, const unsigned char *s, size_t l)
  12. {
  13. struct cookie *c = f->cookie;
  14. size_t k = MIN(c->n, f->wpos - f->wbase);
  15. if (k) {
  16. memcpy(c->s, f->wbase, k);
  17. c->s += k;
  18. c->n -= k;
  19. }
  20. k = MIN(c->n, l);
  21. if (k) {
  22. memcpy(c->s, s, k);
  23. c->s += k;
  24. c->n -= k;
  25. }
  26. *c->s = 0;
  27. f->wpos = f->wbase = f->buf;
  28. /* pretend to succeed, even if we discarded extra data */
  29. return l;
  30. }
  31. int vsnprintf(char *restrict s, size_t n, const char *restrict fmt, va_list ap)
  32. {
  33. unsigned char buf[1];
  34. char dummy[1];
  35. struct cookie c = { .s = n ? s : dummy, .n = n ? n-1 : 0 };
  36. FILE f = {
  37. .lbf = EOF,
  38. .write = sn_write,
  39. .lock = -1,
  40. .buf = buf,
  41. .cookie = &c,
  42. };
  43. if (n > INT_MAX) {
  44. errno = EOVERFLOW;
  45. return -1;
  46. }
  47. *c.s = 0;
  48. return vfprintf(&f, fmt, ap);
  49. }