vsnprintf.c 936 B

123456789101112131415161718192021222324252627282930313233343536373839404142
  1. #include "stdio_impl.h"
  2. #include <limits.h>
  3. #include <string.h>
  4. #include <errno.h>
  5. #include <stdint.h>
  6. static size_t sn_write(FILE *f, const unsigned char *s, size_t l)
  7. {
  8. size_t k = f->wend - f->wpos;
  9. if (k > l) k = l;
  10. memcpy(f->wpos, s, k);
  11. f->wpos += k;
  12. /* pretend to succeed, but discard extra data */
  13. return l;
  14. }
  15. int vsnprintf(char *restrict s, size_t n, const char *restrict fmt, va_list ap)
  16. {
  17. int r;
  18. char b;
  19. FILE f = { .lbf = EOF, .write = sn_write, .lock = -1 };
  20. if (n-1 > INT_MAX-1) {
  21. if (n) {
  22. errno = EOVERFLOW;
  23. return -1;
  24. }
  25. s = &b;
  26. n = 1;
  27. }
  28. /* Ensure pointers don't wrap if "infinite" n is passed in */
  29. if (n > (char *)0+SIZE_MAX-s-1) n = (char *)0+SIZE_MAX-s-1;
  30. f.buf_size = n;
  31. f.buf = f.wpos = (void *)s;
  32. f.wbase = f.wend = (void *)(s+n);
  33. r = vfprintf(&f, fmt, ap);
  34. /* Null-terminate, overwriting last char if dest buffer is full */
  35. if (n) f.wpos[-(f.wpos == f.wend)] = 0;
  36. return r;
  37. }