Mercurial > dovecot > original-hg > dovecot-1.2
view src/lib/printf-upper-bound.c @ 1329:ae229b7acb4c HEAD
Mailbox names are now sent through imap-quoter instead of just escaping it.
This means that mailbox names that would require escapes are instead sent
as literals now.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Wed, 02 Apr 2003 05:05:38 +0300 |
parents | 8676ba4f3ba9 |
children | 520e3a0496db |
line wrap: on
line source
/* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald Modified by the GLib Team and others 1997-1999. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "lib.h" #include "printf-upper-bound.h" typedef union _GDoubleIEEE754 GDoubleIEEE754; #define G_IEEE754_DOUBLE_BIAS (1023) /* multiply with base2 exponent to get base10 exponent (nomal numbers) */ #define G_LOG_2_BASE_10 (0.30102999566398119521) #if G_BYTE_ORDER == G_LITTLE_ENDIAN union _GDoubleIEEE754 { double v_double; struct { unsigned int mantissa_low : 32; unsigned int mantissa_high : 20; unsigned int biased_exponent : 11; unsigned int sign : 1; } mpn; }; #elif G_BYTE_ORDER == G_BIG_ENDIAN union _GDoubleIEEE754 { double v_double; struct { unsigned int sign : 1; unsigned int biased_exponent : 11; unsigned int mantissa_high : 20; unsigned int mantissa_low : 32; } mpn; }; #else /* !G_LITTLE_ENDIAN && !G_BIG_ENDIAN */ #error unknown ENDIAN type #endif /* !G_LITTLE_ENDIAN && !G_BIG_ENDIAN */ typedef struct { unsigned int min_width; unsigned int precision; int alternate_format, zero_padding, adjust_left, locale_grouping; int add_space, add_sign, possible_sign, seen_precision; int mod_long, mod_extra_long; } PrintfArgSpec; #if (SIZEOF_LONG > 4) || (SIZEOF_VOID_P > 4) # define HONOUR_LONGS 1 #else # define HONOUR_LONGS 0 #endif size_t printf_string_upper_bound(const char *format, va_list args) { size_t len = 1; if (!format) return len; while (*format) { register char c = *format++; if (c != '%') len += 1; else /* (c == '%') */ { PrintfArgSpec spec; int seen_l = FALSE, conv_done = FALSE; unsigned int conv_len = 0; memset(&spec, 0, sizeof(spec)); do { c = *format++; switch (c) { GDoubleIEEE754 u_double; unsigned int v_uint; int v_int; const char *v_string; /* beware of positional parameters */ case '$': i_panic("unable to handle positional parameters (%%n$)"); break; /* parse flags */ case '#': spec.alternate_format = TRUE; break; case '0': spec.zero_padding = TRUE; break; case '-': spec.adjust_left = TRUE; break; case ' ': spec.add_space = TRUE; break; case '+': spec.add_sign = TRUE; break; case '\'': spec.locale_grouping = TRUE; break; /* parse output size specifications */ case '.': spec.seen_precision = TRUE; break; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': v_uint = c - '0'; c = *format; while (c >= '0' && c <= '9') { format++; v_uint = v_uint * 10 + (c - '0'); c = *format; } if (spec.seen_precision) spec.precision = I_MAX (spec.precision, v_uint); else spec.min_width = I_MAX (spec.min_width, v_uint); break; case '*': v_int = va_arg (args, int); if (spec.seen_precision) { /* forget about negative precision */ if (v_int >= 0) spec.precision = I_MAX ((int)spec.precision, v_int); } else { if (v_int < 0) { v_int = - v_int; spec.adjust_left = TRUE; } spec.min_width = I_MAX ((int)spec.min_width, v_int); } break; /* parse type modifiers */ case 'h': /* ignore */ break; case 'l': if (!seen_l) { spec.mod_long = TRUE; seen_l = TRUE; break; } /* else, fall through */ case 'L': spec.mod_long = TRUE; spec.mod_extra_long = TRUE; break; /* parse output conversions */ case '%': conv_len += 1; break; case 'o': conv_len += 2; /* fall through */ case 'd': case 'i': conv_len += 1; /* sign */ /* fall through */ case 'u': conv_len += 4; /* fall through */ case 'x': case 'X': spec.possible_sign = TRUE; conv_len += 10; if (spec.mod_long && HONOUR_LONGS) conv_len *= 2; if (spec.mod_extra_long) conv_len *= 2; if (spec.mod_extra_long) { #if SIZEOF_LONG_LONG > 0 (void) va_arg (args, long long); #else i_panic("mod_extra_long not supported"); #endif } else if (spec.mod_long) (void) va_arg (args, long); else (void) va_arg (args, int); break; case 'A': case 'a': /* 0x */ conv_len += 2; /* fall through */ case 'g': case 'G': case 'e': case 'E': case 'f': spec.possible_sign = TRUE; /* n . dddddddddddddddddddddddd E +- eeee */ conv_len += 1 + 1 + I_MAX (24, spec.precision) + 1 + 1 + 4; if (spec.mod_extra_long) i_panic("unable to handle long double"); #ifdef HAVE_LONG_DOUBLE #error need to implement special handling for long double #endif u_double.v_double = va_arg (args, double); /* %f can expand up to all significant digits before '.' (308) */ if (c == 'f' && u_double.mpn.biased_exponent > 0 && u_double.mpn.biased_exponent < 2047) { int exp = u_double.mpn.biased_exponent; exp -= G_IEEE754_DOUBLE_BIAS; exp = exp * G_LOG_2_BASE_10 + 1; conv_len += exp; } /* some printf() implementations require extra padding for rounding */ conv_len += 2; /* we can't really handle locale specific grouping here */ if (spec.locale_grouping) conv_len *= 2; break; case 'c': conv_len += spec.mod_long ? MB_LEN_MAX : 1; (void) va_arg (args, int); break; case 's': v_string = va_arg (args, char*); if (!v_string) conv_len += 8; /* hold "(null)" */ else if (spec.seen_precision) conv_len += spec.precision; else conv_len += strlen (v_string); conv_done = TRUE; if (spec.mod_long) i_panic("unable to handle wide char strings"); break; case 'p': spec.alternate_format = TRUE; conv_len += 10; if (HONOUR_LONGS) conv_len *= 2; conv_done = TRUE; (void) va_arg (args, void*); break; case 'm': /* normally we shouldn't even get here, but we could be just checking the format string is valid before giving the format to vsyslog(). */ conv_len += strlen(strerror(errno)) + 256; break; /* handle invalid cases */ case '\000': /* no conversion specification, bad bad */ i_panic("Missing conversion specifier"); break; default: i_panic("unable to handle `%c' while parsing format", c); break; } conv_done |= conv_len > 0; } while (!conv_done); /* handle width specifications */ conv_len = I_MAX (conv_len, I_MAX (spec.precision, spec.min_width)); /* handle flags */ conv_len += spec.alternate_format ? 2 : 0; conv_len += (spec.add_space || spec.add_sign || spec.possible_sign); /* finally done */ len += conv_len; } /* else (c == '%') */ } /* while (*format) */ return len; }