| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272 |
- /*
- * "$Id: vsnprintf.c 9325 2012-04-05 05:12:30Z fabien $"
- *
- * snprintf() and vsnprintf() functions for the Fast Light Tool Kit (FLTK).
- *
- * Copyright 1998-2010 by Bill Spitzak and others.
- *
- * This library is free software. Distribution and use rights are outlined in
- * the file "COPYING" which should have been included with this file. If this
- * file is missing or damaged, see the license at:
- *
- * http://www.fltk.org/COPYING.php
- *
- * Please report all bugs and problems on the following page:
- *
- * http://www.fltk.org/str.php
- */
- #include <stdio.h>
- #include "flstring.h"
- #ifdef HAVE_SYS_STDTYPES_H
- # include <sys/stdtypes.h>
- #endif /* HAVE_SYS_STDTYPES_H */
- #ifdef __cplusplus
- extern "C" {
- #endif
- int fl_vsnprintf(char* buffer, size_t bufsize, const char* format, va_list ap) {
- char *bufptr, /* Pointer to position in buffer */
- *bufend, /* Pointer to end of buffer */
- sign, /* Sign of format width */
- size, /* Size character (h, l, L) */
- type; /* Format type character */
- int width, /* Width of field */
- prec; /* Number of characters of precision */
- char tformat[100], /* Temporary format string for sprintf() */
- *tptr, /* Pointer into temporary format */
- temp[1024]; /* Buffer for formatted numbers */
- char *s; /* Pointer to string */
- int slen; /* Length of string */
- int bytes; /* Total number of bytes needed */
- /*
- * Loop through the format string, formatting as needed...
- */
- bufptr = buffer;
- bufend = buffer + bufsize - 1;
- bytes = 0;
- while (*format) {
- if (*format == '%') {
- tptr = tformat;
- *tptr++ = *format++;
- if (*format == '%') {
- if (bufptr && bufptr < bufend) *bufptr++ = *format;
- bytes ++;
- format ++;
- continue;
- } else if (strchr(" -+#\'", *format)) {
- *tptr++ = *format;
- sign = *format++;
- } else sign = 0;
- if (*format == '*') {
- /* Get width from argument... */
- format ++;
- width = va_arg(ap, int);
- snprintf(tptr, sizeof(tformat) - (tptr - tformat), "%d", width);
- tptr += strlen(tptr);
- } else {
- width = 0;
- while (isdigit(*format & 255)) {
- if (tptr < (tformat + sizeof(tformat) - 1)) *tptr++ = *format;
- width = width * 10 + *format++ - '0';
- }
- }
- if (*format == '.') {
- if (tptr < (tformat + sizeof(tformat) - 1)) *tptr++ = *format;
- format ++;
- if (*format == '*') {
- /* Get precision from argument... */
- format ++;
- prec = va_arg(ap, int);
- snprintf(tptr, sizeof(tformat) - (tptr - tformat), "%d", prec);
- tptr += strlen(tptr);
- } else {
- prec = 0;
- while (isdigit(*format & 255)) {
- if (tptr < (tformat + sizeof(tformat) - 1)) *tptr++ = *format;
- prec = prec * 10 + *format++ - '0';
- }
- }
- } else prec = -1;
- size = '\0';
- if (*format == 'l' && format[1] == 'l') {
- size = 'L';
- if (tptr < (tformat + sizeof(tformat) - 2)) {
- *tptr++ = 'l';
- *tptr++ = 'l';
- }
- format += 2;
- } else if (*format == 'h' || *format == 'l' || *format == 'L') {
- if (tptr < (tformat + sizeof(tformat) - 1)) *tptr++ = *format;
- size = *format++;
- }
- if (!*format) break;
- if (tptr < (tformat + sizeof(tformat) - 1)) *tptr++ = *format;
- type = *format++;
- *tptr = '\0';
- switch (type) {
- case 'E' : /* Floating point formats */
- case 'G' :
- case 'e' :
- case 'f' :
- case 'g' :
- if ((width + 2) > sizeof(temp)) break;
- sprintf(temp, tformat, va_arg(ap, double));
- bytes += (int) strlen(temp);
- if (bufptr) {
- if ((bufptr + strlen(temp)) > bufend) {
- strncpy(bufptr, temp, (size_t)(bufend - bufptr));
- bufptr = bufend;
- } else {
- strcpy(bufptr, temp);
- bufptr += strlen(temp);
- }
- }
- break;
- case 'B' : /* Integer formats */
- case 'X' :
- case 'b' :
- case 'd' :
- case 'i' :
- case 'o' :
- case 'u' :
- case 'x' :
- if ((width + 2) > sizeof(temp)) break;
- #ifdef HAVE_LONG_LONG
- if (size == 'L')
- sprintf(temp, tformat, va_arg(ap, long long));
- else
- #endif /* HAVE_LONG_LONG */
- if (size == 'l')
- sprintf(temp, tformat, va_arg(ap, long));
- else
- sprintf(temp, tformat, va_arg(ap, int));
- bytes += (int) strlen(temp);
- if (bufptr) {
- if ((bufptr + strlen(temp)) > bufend) {
- strncpy(bufptr, temp, (size_t)(bufend - bufptr));
- bufptr = bufend;
- } else {
- strcpy(bufptr, temp);
- bufptr += strlen(temp);
- }
- }
- break;
-
- case 'p' : /* Pointer value */
- if ((width + 2) > sizeof(temp)) break;
- sprintf(temp, tformat, va_arg(ap, void *));
- bytes += (int) strlen(temp);
- if (bufptr) {
- if ((bufptr + strlen(temp)) > bufend) {
- strncpy(bufptr, temp, (size_t)(bufend - bufptr));
- bufptr = bufend;
- } else {
- strcpy(bufptr, temp);
- bufptr += strlen(temp);
- }
- }
- break;
- case 'c' : /* Character or character array */
- bytes += width;
- if (bufptr) {
- if (width <= 1) *bufptr++ = va_arg(ap, int);
- else {
- if ((bufptr + width) > bufend) width = (int) (bufend - bufptr);
- memcpy(bufptr, va_arg(ap, char *), (size_t)width);
- bufptr += width;
- }
- }
- break;
- case 's' : /* String */
- if ((s = va_arg(ap, char *)) == NULL) s = "(null)";
- slen = (int) strlen(s);
- if (slen > width && prec != width) width = slen;
- bytes += width;
- if (bufptr) {
- if ((bufptr + width) > bufend) width = (int) (bufend - bufptr);
- if (slen > width) slen = width;
- if (sign == '-') {
- strncpy(bufptr, s, (size_t)slen);
- memset(bufptr + slen, ' ', (size_t)(width - slen));
- } else {
- memset(bufptr, ' ', (size_t)(width - slen));
- strncpy(bufptr + width - slen, s, (size_t)slen);
- }
- bufptr += width;
- }
- break;
- case 'n' : /* Output number of chars so far */
- *(va_arg(ap, int *)) = bytes;
- break;
- }
- } else {
- bytes ++;
- if (bufptr && bufptr < bufend) *bufptr++ = *format;
- format ++;
- }
- }
- /*
- * Nul-terminate the string and return the number of characters needed.
- */
- if (bufptr) *bufptr = '\0';
- return (bytes);
- }
- int fl_snprintf(char* str, size_t size, const char* fmt, ...) {
- int ret;
- va_list ap;
- va_start(ap, fmt);
- ret = vsnprintf(str, size, fmt, ap);
- va_end(ap);
- return ret;
- }
- #ifdef __cplusplus
- }
- #endif
- /*
- * End of "$Id: vsnprintf.c 9325 2012-04-05 05:12:30Z fabien $".
- */
|