From 609e9edb251e637e1b1c8410927308784ade37f3 Mon Sep 17 00:00:00 2001 From: Assar Westerlund Date: Mon, 2 Jul 2001 23:13:23 +0000 Subject: [PATCH] rewrite so that it does not stop as soon as there are no more characters to print, we need to figure out how long the string would have to be. this also fixes snprintf(NULL, 0 git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@10247 ec53bebd-3082-4978-b11e-865c3cabbd6b --- lib/roken/snprintf.c | 250 +++++++++++++++++++++---------------------- 1 file changed, 121 insertions(+), 129 deletions(-) diff --git a/lib/roken/snprintf.c b/lib/roken/snprintf.c index a340e9084..7f2ecfb5c 100644 --- a/lib/roken/snprintf.c +++ b/lib/roken/snprintf.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995-2000 Kungliga Tekniska Högskolan + * Copyright (c) 1995-2001 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -60,27 +60,22 @@ struct state { unsigned char *theend; size_t sz; size_t max_sz; - int (*append_char)(struct state *, unsigned char); - int (*reserve)(struct state *, size_t); + void (*append_char)(struct state *, unsigned char); /* XXX - methods */ }; -#ifndef HAVE_VSNPRINTF +#if !defined(HAVE_VSNPRINTF) || defined(TEST_SNPRINTF) static int sn_reserve (struct state *state, size_t n) { return state->s + n > state->theend; } -static int +static void sn_append_char (struct state *state, unsigned char c) { - if (sn_reserve (state, 1)) { - return 1; - } else { + if (!sn_reserve (state, 1)) *state->s++ = c; - return 0; - } } #endif @@ -107,15 +102,21 @@ as_reserve (struct state *state, size_t n) return 0; } -static int +static void as_append_char (struct state *state, unsigned char c) { - if(as_reserve (state, 1)) - return 1; - else { + if(!as_reserve (state, 1)) *state->s++ = c; - return 0; - } +} + +/* + * is # supposed to do anything? + */ + +static int +use_alternative (int flags, unsigned long num, unsigned base) +{ + return flags & alternate_flag && (base == 16 || base == 8) && num != 0; } static int @@ -125,6 +126,7 @@ append_number(struct state *state, { int len = 0; int i; + unsigned long n = num; /* given precision, ignore zero flag */ if(prec != -1) @@ -132,23 +134,21 @@ append_number(struct state *state, else prec = 1; /* zero value with zero precision -> "" */ - if(prec == 0 && num == 0) + if(prec == 0 && n == 0) return 0; do{ - if((*state->append_char)(state, rep[num % base])) - return 1; - len++; - num /= base; - }while(num); + (*state->append_char)(state, rep[n % base]); + ++len; + n /= base; + } while(n); prec -= len; /* pad with prec zeros */ while(prec-- > 0){ - if((*state->append_char)(state, '0')) - return 1; - len++; + (*state->append_char)(state, '0'); + ++len; } /* add length of alternate prefix (added later) to len */ - if(flags & alternate_flag && (base == 16 || base == 8)) + if(use_alternative(flags, num, base)) len += base / 8; /* pad with zeros */ if(flags & zero_flag){ @@ -156,32 +156,26 @@ append_number(struct state *state, if(minusp || (flags & space_flag) || (flags & plus_flag)) width--; while(width-- > 0){ - if((*state->append_char)(state, '0')) - return 1; + (*state->append_char)(state, '0'); len++; } } /* add alternate prefix */ - if(flags & alternate_flag && (base == 16 || base == 8)){ + if(use_alternative(flags, num, base)){ if(base == 16) - if((*state->append_char)(state, rep[10] + 23)) /* XXX */ - return 1; - if((*state->append_char)(state, '0')) - return 1; + (*state->append_char)(state, rep[10] + 23); /* XXX */ + (*state->append_char)(state, '0'); } /* add sign */ if(minusp){ - if((*state->append_char)(state, '-')) - return 1; - len++; + (*state->append_char)(state, '-'); + ++len; } else if(flags & plus_flag) { - if((*state->append_char)(state, '+')) - return 1; - len++; + (*state->append_char)(state, '+'); + ++len; } else if(flags & space_flag) { - if((*state->append_char)(state, ' ')) - return 1; - len++; + (*state->append_char)(state, ' '); + ++len; } if(flags & minus_flag) /* swap before padding with spaces */ @@ -192,9 +186,8 @@ append_number(struct state *state, } width -= len; while(width-- > 0){ - if((*state->append_char)(state, ' ')) - return 1; - len++; + (*state->append_char)(state, ' '); + ++len; } if(!(flags & minus_flag)) /* swap after padding with spaces */ @@ -203,42 +196,51 @@ append_number(struct state *state, state->s[-i-1] = state->s[-len+i]; state->s[-len+i] = c; } - - return 0; + return len; } +/* + * return length + */ + static int append_string (struct state *state, - unsigned char *arg, + const unsigned char *arg, int width, int prec, int flags) { + int len = 0; + if(arg == NULL) - arg = (unsigned char*)"(null)"; + arg = (const unsigned char*)"(null)"; if(prec != -1) width -= prec; else - width -= strlen((char *)arg); + width -= strlen((const char *)arg); if(!(flags & minus_flag)) - while(width-- > 0) - if((*state->append_char) (state, ' ')) - return 1; + while(width-- > 0) { + (*state->append_char) (state, ' '); + ++len; + } if (prec != -1) { - while (*arg && prec--) - if ((*state->append_char) (state, *arg++)) - return 1; + while (*arg && prec--) { + (*state->append_char) (state, *arg++); + ++len; + } } else { - while (*arg) - if ((*state->append_char) (state, *arg++)) - return 1; + while (*arg) { + (*state->append_char) (state, *arg++); + ++len; + } } if(flags & minus_flag) - while(width-- > 0) - if((*state->append_char) (state, ' ')) - return 1; - return 0; + while(width-- > 0) { + (*state->append_char) (state, ' '); + ++len; + } + return len; } static int @@ -247,16 +249,18 @@ append_char(struct state *state, int width, int flags) { - while(!(flags & minus_flag) && --width > 0) - if((*state->append_char) (state, ' ')) - return 1; - - if((*state->append_char) (state, arg)) - return 1; - while((flags & minus_flag) && --width > 0) - if((*state->append_char) (state, ' ')) - return 1; - + int len = 0; + + while(!(flags & minus_flag) && --width > 0) { + (*state->append_char) (state, ' ') ; + ++len; + } + (*state->append_char) (state, arg); + ++len; + while((flags & minus_flag) && --width > 0) { + (*state->append_char) (state, ' '); + ++len; + } return 0; } @@ -273,7 +277,7 @@ else \ res = (unsig int)va_arg(arg, unsig int) /* - * zyxprintf - return 0 or -1 + * zyxprintf - return length, as snprintf */ static int @@ -281,6 +285,7 @@ xyzprintf (struct state *state, const char *char_format, va_list ap) { const unsigned char *format = (const unsigned char *)char_format; unsigned char c; + int len = 0; while((c = *format++)) { if (c == '%') { @@ -350,16 +355,15 @@ xyzprintf (struct state *state, const char *char_format, va_list ap) switch (c) { case 'c' : - if(append_char(state, va_arg(ap, int), width, flags)) - return -1; + append_char(state, va_arg(ap, int), width, flags); + ++len; break; case 's' : - if (append_string(state, - va_arg(ap, unsigned char*), - width, - prec, - flags)) - return -1; + len += append_string(state, + va_arg(ap, unsigned char*), + width, + prec, + flags); break; case 'd' : case 'i' : { @@ -375,9 +379,8 @@ xyzprintf (struct state *state, const char *char_format, va_list ap) } else num = arg; - if (append_number (state, num, 10, "0123456789", - width, prec, flags, minusp)) - return -1; + len += append_number (state, num, 10, "0123456789", + width, prec, flags, minusp); break; } case 'u' : { @@ -385,9 +388,8 @@ xyzprintf (struct state *state, const char *char_format, va_list ap) PARSE_INT_FORMAT(arg, ap, unsigned); - if (append_number (state, arg, 10, "0123456789", - width, prec, flags, 0)) - return -1; + len += append_number (state, arg, 10, "0123456789", + width, prec, flags, 0); break; } case 'o' : { @@ -395,9 +397,8 @@ xyzprintf (struct state *state, const char *char_format, va_list ap) PARSE_INT_FORMAT(arg, ap, unsigned); - if (append_number (state, arg, 010, "01234567", - width, prec, flags, 0)) - return -1; + len += append_number (state, arg, 010, "01234567", + width, prec, flags, 0); break; } case 'x' : { @@ -405,9 +406,8 @@ xyzprintf (struct state *state, const char *char_format, va_list ap) PARSE_INT_FORMAT(arg, ap, unsigned); - if (append_number (state, arg, 0x10, "0123456789abcdef", - width, prec, flags, 0)) - return -1; + len += append_number (state, arg, 0x10, "0123456789abcdef", + width, prec, flags, 0); break; } case 'X' :{ @@ -415,17 +415,15 @@ xyzprintf (struct state *state, const char *char_format, va_list ap) PARSE_INT_FORMAT(arg, ap, unsigned); - if (append_number (state, arg, 0x10, "0123456789ABCDEF", - width, prec, flags, 0)) - return -1; + len += append_number (state, arg, 0x10, "0123456789ABCDEF", + width, prec, flags, 0); break; } case 'p' : { unsigned long arg = (unsigned long)va_arg(ap, void*); - if (append_number (state, arg, 0x10, "0123456789ABCDEF", - width, prec, flags, 0)) - return -1; + len += append_number (state, arg, 0x10, "0123456789ABCDEF", + width, prec, flags, 0); break; } case 'n' : { @@ -437,23 +435,24 @@ xyzprintf (struct state *state, const char *char_format, va_list ap) --format; /* FALLTHROUGH */ case '%' : - if ((*state->append_char)(state, c)) - return -1; + (*state->append_char)(state, c); + ++len; break; default : - if ( (*state->append_char)(state, '%') - || (*state->append_char)(state, c)) - return -1; + (*state->append_char)(state, '%'); + (*state->append_char)(state, c); + len += 2; break; } - } else - if ((*state->append_char) (state, c)) - return -1; + } else { + (*state->append_char) (state, c); + ++len; + } } - return 0; + return len; } -#ifndef HAVE_SNPRINTF +#if !defined(HAVE_SNPRINTF) || defined(TEST_SNPRINTF) int snprintf (char *str, size_t sz, const char *format, ...) { @@ -484,7 +483,7 @@ snprintf (char *str, size_t sz, const char *format, ...) } #endif -#ifndef HAVE_ASPRINTF +#if !defined(HAVE_ASPRINTF) || defined(TEST_SNPRINTF) int asprintf (char **ret, const char *format, ...) { @@ -514,7 +513,7 @@ asprintf (char **ret, const char *format, ...) } #endif -#ifndef HAVE_ASNPRINTF +#if !defined(HAVE_ASNPRINTF) || defined(TEST_SNPRINTF) int asnprintf (char **ret, size_t max_sz, const char *format, ...) { @@ -544,7 +543,7 @@ asnprintf (char **ret, size_t max_sz, const char *format, ...) } #endif -#ifndef HAVE_VASPRINTF +#if !defined(HAVE_VASPRINTF) || defined(TEST_SNPRINTF) int vasprintf (char **ret, const char *format, va_list args) { @@ -553,12 +552,11 @@ vasprintf (char **ret, const char *format, va_list args) #endif -#ifndef HAVE_VASNPRINTF +#if !defined(HAVE_VASNPRINTF) || defined(TEST_SNPRINTF) int vasnprintf (char **ret, size_t max_sz, const char *format, va_list args) { int st; - size_t len; struct state state; state.max_sz = max_sz; @@ -571,10 +569,9 @@ vasnprintf (char **ret, size_t max_sz, const char *format, va_list args) state.s = state.str; state.theend = state.s + state.sz - 1; state.append_char = as_append_char; - state.reserve = as_reserve; st = xyzprintf (&state, format, args); - if (st) { + if (st > state.sz) { free (state.str); *ret = NULL; return -1; @@ -582,20 +579,19 @@ vasnprintf (char **ret, size_t max_sz, const char *format, va_list args) char *tmp; *state.s = '\0'; - len = state.s - state.str; - tmp = realloc (state.str, len+1); + tmp = realloc (state.str, st+1); if (tmp == NULL) { free (state.str); *ret = NULL; return -1; } *ret = tmp; - return len; + return st; } } #endif -#ifndef HAVE_VSNPRINTF +#if !defined(HAVE_VSNPRINTF) || defined(TEST_SNPRINTF) int vsnprintf (char *str, size_t sz, const char *format, va_list args) { @@ -607,16 +603,12 @@ vsnprintf (char *str, size_t sz, const char *format, va_list args) state.sz = sz; state.str = ustr; state.s = ustr; - state.theend = ustr + sz - 1; + state.theend = ustr + sz - (sz > 0); state.append_char = sn_append_char; - state.reserve = sn_reserve; ret = xyzprintf (&state, format, args); - *state.s = '\0'; - if (ret) - return sz; - else - return state.s - state.str; + if (state.s != NULL) + *state.s = '\0'; + return ret; } #endif -