Alexandre Julliard : libwine: Fix vsnprintfW string formatting to handle alignment and padding.
Alexandre Julliard
julliard at winehq.org
Sun Jan 4 09:09:10 CST 2009
Module: wine
Branch: master
Commit: 9428dfe71a83c175108b8a936db5768f5d6558c8
URL: http://source.winehq.org/git/wine.git/?a=commit;h=9428dfe71a83c175108b8a936db5768f5d6558c8
Author: Alexandre Julliard <julliard at winehq.org>
Date: Sun Jan 4 14:13:33 2009 +0100
libwine: Fix vsnprintfW string formatting to handle alignment and padding.
Also fix handling of pointer format for 64-bit.
---
libs/wine/string.c | 84 +++++++++++++++++++++++++++++++++++++++++++--------
1 files changed, 70 insertions(+), 14 deletions(-)
diff --git a/libs/wine/string.c b/libs/wine/string.c
index 195af6c..b45de92 100644
--- a/libs/wine/string.c
+++ b/libs/wine/string.c
@@ -18,6 +18,7 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
+#include <assert.h>
#include <limits.h>
#include <stdio.h>
@@ -298,6 +299,51 @@ noconv:
}
+/* format a WCHAR string according to a printf format; helper for vsnprintfW */
+static int format_string( WCHAR *buffer, size_t len, const char *format, const WCHAR *str )
+{
+ size_t count = 0;
+ int i, left_align = 0, width = 0, max = 0;
+
+ assert( *format == '%' );
+ format++; /* skip '%' */
+
+ while (*format == '0' || *format == '+' || *format == '-' || *format == ' ' || *format == '#')
+ {
+ if (*format == '-') left_align = 1;
+ format++;
+ }
+
+ while (isdigit(*format)) width = width * 10 + *format++ - '0';
+
+ if (*format == '.')
+ {
+ format++;
+ while (isdigit(*format)) max = max * 10 + *format++ - '0';
+ for (i = 0; i < max; i++) if (!str[i]) max = i;
+ }
+ else max = strlenW(str);
+
+ assert( *format == 's' );
+
+ if (!left_align && width > max)
+ {
+ if ((count += width - max) >= len) return -1;
+ for (i = 0; i < width - max; i++) *buffer++ = ' ';
+ }
+
+ if ((count += max) >= len) return -1;
+ memcpy( buffer, str, max * sizeof(WCHAR) );
+ buffer += max;
+
+ if (left_align && width > max)
+ {
+ if ((count += width - max) >= len) return -1;
+ for (i = 0; i < width - max; i++) *buffer++ = ' ';
+ }
+ return count;
+}
+
int vsnprintfW(WCHAR *str, size_t len, const WCHAR *format, va_list valist)
{
unsigned int written = 0;
@@ -372,23 +418,34 @@ int vsnprintfW(WCHAR *str, size_t len, const WCHAR *format, va_list valist)
{
static const WCHAR none[] = { '(','n','u','l','l',')',0 };
const WCHAR *wstr = va_arg(valist, const WCHAR *);
- const WCHAR *striter = wstr ? wstr : none;
- while (*striter)
- {
- if (written++ >= len)
- return -1;
- *str++ = *striter++;
- }
+ int count;
+
+ *fmta++ = 's';
+ *fmta = 0;
+ count = format_string( str, len - written, fmtbufa, wstr ? wstr : none );
+ if (count == -1) return -1;
+ str += count;
+ written += count;
iter++;
break;
}
case 'c':
- if (written++ >= len)
- return -1;
- *str++ = (WCHAR)va_arg(valist, int);
+ {
+ WCHAR wstr[2];
+ int count;
+
+ wstr[0] = va_arg(valist, int);
+ wstr[1] = 0;
+ *fmta++ = 's';
+ *fmta = 0;
+ count = format_string( str, len - written, fmtbufa, wstr );
+ if (count == -1) return -1;
+ str += count;
+ written += count;
iter++;
break;
+ }
default:
{
@@ -396,7 +453,8 @@ int vsnprintfW(WCHAR *str, size_t len, const WCHAR *format, va_list valist)
/* FIXME: for unrecognised types, should ignore % when printing */
char *bufaiter = bufa;
if (*iter == 'p')
- sprintf(bufaiter, "%08lX", va_arg(valist, long));
+ sprintf(bufaiter, "%0*lX", 2 * (int)sizeof(void*),
+ (unsigned long)va_arg(valist, void *));
else
{
*fmta++ = *iter;
@@ -408,9 +466,7 @@ int vsnprintfW(WCHAR *str, size_t len, const WCHAR *format, va_list valist)
sprintf(bufaiter, fmtbufa, va_arg(valist, double));
else
{
- /* FIXME: On 32 bit systems this doesn't handle int 64's.
- * on 64 bit systems this doesn't work for 32 bit types
- */
+ /* FIXME: On 32 bit systems this doesn't handle int 64's. */
sprintf(bufaiter, fmtbufa, va_arg(valist, void *));
}
}
More information about the wine-cvs
mailing list