vsnprintf.c raw

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