ReactOS  0.4.11-dev-721-g95bc44e
wsprintf.c
Go to the documentation of this file.
1 /*
2  * wsprintf functions
3  *
4  * Copyright 1996 Alexandre Julliard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  *
20  * NOTE:
21  * This code is duplicated in user32. If you change something here make sure
22  * to change it in user32 too.
23  */
24 
25 #include <stdarg.h>
26 #include <string.h>
27 #include <stdio.h>
28 
29 #include "windef.h"
30 #include "winbase.h"
31 #define NO_SHLWAPI_REG
32 #include "shlwapi.h"
33 
34 #include "wine/debug.h"
35 
37 
38 
39 #define WPRINTF_LEFTALIGN 0x0001 /* Align output on the left ('-' prefix) */
40 #define WPRINTF_PREFIX_HEX 0x0002 /* Prefix hex with 0x ('#' prefix) */
41 #define WPRINTF_ZEROPAD 0x0004 /* Pad with zeros ('0' prefix) */
42 #define WPRINTF_LONG 0x0008 /* Long arg ('l' prefix) */
43 #define WPRINTF_SHORT 0x0010 /* Short arg ('h' prefix) */
44 #define WPRINTF_UPPER_HEX 0x0020 /* Upper-case hex ('X' specifier) */
45 #define WPRINTF_WIDE 0x0040 /* Wide arg ('w' prefix) */
46 #define WPRINTF_INTPTR 0x0080 /* Pointer-size arg ('I' prefix) */
47 #define WPRINTF_I64 0x0100 /* 64-bit arg ('I64' prefix) */
48 
49 typedef enum
50 {
59 } WPRINTF_TYPE;
60 
61 typedef struct
62 {
68 
69 typedef union {
75 } WPRINTF_DATA;
76 
77 static const CHAR null_stringA[] = "(null)";
78 static const WCHAR null_stringW[] = { '(', 'n', 'u', 'l', 'l', ')', 0 };
79 
80 /***********************************************************************
81  * WPRINTF_ParseFormatA
82  *
83  * Parse a format specification. A format specification has the form:
84  *
85  * [-][#][0][width][.precision]type
86  *
87  * Return value is the length of the format specification in characters.
88  */
90 {
91  LPCSTR p = format;
92 
93  res->flags = 0;
94  res->width = 0;
95  res->precision = 0;
96  if (*p == '-') { res->flags |= WPRINTF_LEFTALIGN; p++; }
97  if (*p == '#') { res->flags |= WPRINTF_PREFIX_HEX; p++; }
98  if (*p == '0') { res->flags |= WPRINTF_ZEROPAD; p++; }
99  while ((*p >= '0') && (*p <= '9')) /* width field */
100  {
101  res->width = res->width * 10 + *p - '0';
102  p++;
103  }
104  if (*p == '.') /* precision field */
105  {
106  p++;
107  while ((*p >= '0') && (*p <= '9'))
108  {
109  res->precision = res->precision * 10 + *p - '0';
110  p++;
111  }
112  }
113  if (*p == 'l') { res->flags |= WPRINTF_LONG; p++; }
114  else if (*p == 'h') { res->flags |= WPRINTF_SHORT; p++; }
115  else if (*p == 'w') { res->flags |= WPRINTF_WIDE; p++; }
116  else if (*p == 'I')
117  {
118  if (p[1] == '6' && p[2] == '4') { res->flags |= WPRINTF_I64; p += 3; }
119  else if (p[1] == '3' && p[2] == '2') p += 3;
120  else { res->flags |= WPRINTF_INTPTR; p++; }
121  }
122  switch(*p)
123  {
124  case 'c':
125  res->type = (res->flags & WPRINTF_LONG) ? WPR_WCHAR : WPR_CHAR;
126  break;
127  case 'C':
128  res->type = (res->flags & WPRINTF_SHORT) ? WPR_CHAR : WPR_WCHAR;
129  break;
130  case 'd':
131  case 'i':
132  res->type = WPR_SIGNED;
133  break;
134  case 's':
135  res->type = (res->flags & (WPRINTF_LONG |WPRINTF_WIDE)) ? WPR_WSTRING : WPR_STRING;
136  break;
137  case 'S':
139  break;
140  case 'u':
141  res->type = WPR_UNSIGNED;
142  break;
143  case 'p':
144  res->width = 2 * sizeof(void *);
146  /* fall through */
147  case 'X':
148  res->flags |= WPRINTF_UPPER_HEX;
149  /* fall through */
150  case 'x':
151  res->type = WPR_HEXA;
152  break;
153  default: /* unknown format char */
154  res->type = WPR_UNKNOWN;
155  p--; /* print format as normal char */
156  break;
157  }
158  return (INT)(p - format) + 1;
159 }
160 
161 
162 /***********************************************************************
163  * WPRINTF_ParseFormatW
164  *
165  * Parse a format specification. A format specification has the form:
166  *
167  * [-][#][0][width][.precision]type
168  *
169  * Return value is the length of the format specification in characters.
170  */
172 {
173  LPCWSTR p = format;
174 
175  res->flags = 0;
176  res->width = 0;
177  res->precision = 0;
178  if (*p == '-') { res->flags |= WPRINTF_LEFTALIGN; p++; }
179  if (*p == '#') { res->flags |= WPRINTF_PREFIX_HEX; p++; }
180  if (*p == '0') { res->flags |= WPRINTF_ZEROPAD; p++; }
181  while ((*p >= '0') && (*p <= '9')) /* width field */
182  {
183  res->width = res->width * 10 + *p - '0';
184  p++;
185  }
186  if (*p == '.') /* precision field */
187  {
188  p++;
189  while ((*p >= '0') && (*p <= '9'))
190  {
191  res->precision = res->precision * 10 + *p - '0';
192  p++;
193  }
194  }
195  if (*p == 'l') { res->flags |= WPRINTF_LONG; p++; }
196  else if (*p == 'h') { res->flags |= WPRINTF_SHORT; p++; }
197  else if (*p == 'w') { res->flags |= WPRINTF_WIDE; p++; }
198  else if (*p == 'I')
199  {
200  if (p[1] == '6' && p[2] == '4') { res->flags |= WPRINTF_I64; p += 3; }
201  else if (p[1] == '3' && p[2] == '2') p += 3;
202  else { res->flags |= WPRINTF_INTPTR; p++; }
203  }
204  switch(*p)
205  {
206  case 'c':
207  res->type = (res->flags & WPRINTF_SHORT) ? WPR_CHAR : WPR_WCHAR;
208  break;
209  case 'C':
210  res->type = (res->flags & WPRINTF_LONG) ? WPR_WCHAR : WPR_CHAR;
211  break;
212  case 'd':
213  case 'i':
214  res->type = WPR_SIGNED;
215  break;
216  case 's':
217  res->type = ((res->flags & WPRINTF_SHORT) && !(res->flags & WPRINTF_WIDE)) ? WPR_STRING : WPR_WSTRING;
218  break;
219  case 'S':
221  break;
222  case 'u':
223  res->type = WPR_UNSIGNED;
224  break;
225  case 'p':
226  res->width = 2 * sizeof(void *);
228  /* fall through */
229  case 'X':
230  res->flags |= WPRINTF_UPPER_HEX;
231  /* fall through */
232  case 'x':
233  res->type = WPR_HEXA;
234  break;
235  default:
236  res->type = WPR_UNKNOWN;
237  p--; /* print format as normal char */
238  break;
239  }
240  return (INT)(p - format) + 1;
241 }
242 
243 
244 /***********************************************************************
245  * WPRINTF_GetLen
246  */
248  LPSTR number, UINT maxlen )
249 {
250  UINT len;
251 
252  if (format->flags & WPRINTF_LEFTALIGN) format->flags &= ~WPRINTF_ZEROPAD;
253  if (format->width > maxlen) format->width = maxlen;
254  switch(format->type)
255  {
256  case WPR_CHAR:
257  case WPR_WCHAR:
258  return (format->precision = 1);
259  case WPR_STRING:
260  if (!arg->lpcstr_view) arg->lpcstr_view = null_stringA;
261  for (len = 0; !format->precision || (len < format->precision); len++)
262  if (!*(arg->lpcstr_view + len)) break;
263  if (len > maxlen) len = maxlen;
264  return (format->precision = len);
265  case WPR_WSTRING:
266  if (!arg->lpcwstr_view) arg->lpcwstr_view = null_stringW;
267  for (len = 0; !format->precision || (len < format->precision); len++)
268  if (!*(arg->lpcwstr_view + len)) break;
269  if (len > maxlen) len = maxlen;
270  return (format->precision = len);
271  case WPR_SIGNED:
272  case WPR_UNSIGNED:
273  case WPR_HEXA:
274  {
275  const char *digits = (format->flags & WPRINTF_UPPER_HEX) ? "0123456789ABCDEF" : "0123456789abcdef";
276  ULONGLONG num = arg->int_view;
277  int base = format->type == WPR_HEXA ? 16 : 10;
278  char buffer[20], *p = buffer, *dst = number;
279 
280  if (format->type == WPR_SIGNED && arg->int_view < 0)
281  {
282  *dst++ = '-';
283  num = -arg->int_view;
284  }
285  if (format->flags & WPRINTF_INTPTR) num = (UINT_PTR)num;
286  else if (!(format->flags & WPRINTF_I64)) num = (UINT)num;
287 
288  do
289  {
290  *p++ = digits[num % base];
291  num /= base;
292  } while (num);
293  while (p > buffer) *dst++ = *(--p);
294  *dst = 0;
295  len = dst - number;
296  break;
297  }
298  default:
299  return 0;
300  }
301  if (len > maxlen) len = maxlen;
302  if (format->precision < len) format->precision = len;
303  if (format->precision > maxlen) format->precision = maxlen;
304  if ((format->flags & WPRINTF_ZEROPAD) && (format->width > format->precision))
305  format->precision = format->width;
306  if (format->flags & WPRINTF_PREFIX_HEX) len += 2;
307  return len;
308 }
309 
310 
311 /***********************************************************************
312  * wvnsprintfA (SHLWAPI.@)
313  *
314  * Print formatted output to a string, up to a maximum number of chars.
315  *
316  * PARAMS
317  * buffer [O] Destination for output string
318  * maxlen [I] Maximum number of characters to write
319  * spec [I] Format string
320  *
321  * RETURNS
322  * Success: The number of characters written.
323  * Failure: -1.
324  */
326 {
328  LPSTR p = buffer;
329  UINT i, len, sign;
330  CHAR number[21]; /* 64bit number can be 18446744073709551616 which is 20 chars. and a \0 */
331  WPRINTF_DATA argData;
332 
333  TRACE("%p %u %s\n", buffer, maxlen, debugstr_a(spec));
334 
335  while (*spec && (maxlen > 1))
336  {
337  if (*spec != '%') { *p++ = *spec++; maxlen--; continue; }
338  spec++;
339  if (*spec == '%') { *p++ = *spec++; maxlen--; continue; }
340  spec += WPRINTF_ParseFormatA( spec, &format );
341 
342  switch(format.type)
343  {
344  case WPR_WCHAR:
345  argData.wchar_view = (WCHAR)va_arg( args, int );
346  break;
347  case WPR_CHAR:
348  argData.char_view = (CHAR)va_arg( args, int );
349  break;
350  case WPR_STRING:
351  argData.lpcstr_view = va_arg( args, LPCSTR );
352  break;
353  case WPR_WSTRING:
354  argData.lpcwstr_view = va_arg( args, LPCWSTR );
355  break;
356  case WPR_HEXA:
357  case WPR_SIGNED:
358  case WPR_UNSIGNED:
359  if (format.flags & WPRINTF_INTPTR) argData.int_view = va_arg(args, INT_PTR);
360  else if (format.flags & WPRINTF_I64) argData.int_view = va_arg(args, LONGLONG);
361  else argData.int_view = va_arg(args, INT);
362  break;
363  default:
364  argData.wchar_view = 0;
365  break;
366  }
367 
368  len = WPRINTF_GetLen( &format, &argData, number, maxlen - 1 );
369  sign = 0;
370  if (!(format.flags & WPRINTF_LEFTALIGN))
371  for (i = format.precision; i < format.width; i++, maxlen--)
372  *p++ = ' ';
373  switch(format.type)
374  {
375  case WPR_WCHAR:
376  *p++ = argData.wchar_view;
377  break;
378  case WPR_CHAR:
379  *p++ = argData.char_view;
380  break;
381  case WPR_STRING:
382  memcpy( p, argData.lpcstr_view, len );
383  p += len;
384  break;
385  case WPR_WSTRING:
386  {
387  LPCWSTR ptr = argData.lpcwstr_view;
388  for (i = 0; i < len; i++) *p++ = (CHAR)*ptr++;
389  }
390  break;
391  case WPR_HEXA:
392  if ((format.flags & WPRINTF_PREFIX_HEX) && (maxlen > 3))
393  {
394  *p++ = '0';
395  *p++ = (format.flags & WPRINTF_UPPER_HEX) ? 'X' : 'x';
396  maxlen -= 2;
397  len -= 2;
398  }
399  /* fall through */
400  case WPR_SIGNED:
401  /* Transfer the sign now, just in case it will be zero-padded*/
402  if (number[0] == '-')
403  {
404  *p++ = '-';
405  sign = 1;
406  }
407  /* fall through */
408  case WPR_UNSIGNED:
409  for (i = len; i < format.precision; i++, maxlen--) *p++ = '0';
410  memcpy( p, number + sign, len - sign );
411  p += len - sign;
412  break;
413  case WPR_UNKNOWN:
414  continue;
415  }
416  if (format.flags & WPRINTF_LEFTALIGN)
417  for (i = format.precision; i < format.width; i++, maxlen--)
418  *p++ = ' ';
419  maxlen -= len;
420  }
421  *p = 0;
422  TRACE("%s\n",debugstr_a(buffer));
423  return (maxlen > 1) ? (INT)(p - buffer) : -1;
424 }
425 
426 
427 /***********************************************************************
428  * wvnsprintfW (SHLWAPI.@)
429  *
430  * See wvnsprintfA.
431  */
433 {
435  LPWSTR p = buffer;
436  UINT i, len, sign;
437  CHAR number[21]; /* 64bit number can be 18446744073709551616 which is 20 chars. and a \0 */
438  WPRINTF_DATA argData;
439 
440  TRACE("%p %u %s\n", buffer, maxlen, debugstr_w(spec));
441 
442  while (*spec && (maxlen > 1))
443  {
444  if (*spec != '%') { *p++ = *spec++; maxlen--; continue; }
445  spec++;
446  if (*spec == '%') { *p++ = *spec++; maxlen--; continue; }
447  spec += WPRINTF_ParseFormatW( spec, &format );
448 
449  switch(format.type)
450  {
451  case WPR_WCHAR:
452  argData.wchar_view = (WCHAR)va_arg( args, int );
453  break;
454  case WPR_CHAR:
455  argData.char_view = (CHAR)va_arg( args, int );
456  break;
457  case WPR_STRING:
458  argData.lpcstr_view = va_arg( args, LPCSTR );
459  break;
460  case WPR_WSTRING:
461  argData.lpcwstr_view = va_arg( args, LPCWSTR );
462  break;
463  case WPR_HEXA:
464  case WPR_SIGNED:
465  case WPR_UNSIGNED:
466  if (format.flags & WPRINTF_INTPTR) argData.int_view = va_arg(args, INT_PTR);
467  else if (format.flags & WPRINTF_I64) argData.int_view = va_arg(args, LONGLONG);
468  else argData.int_view = va_arg(args, INT);
469  break;
470  default:
471  argData.wchar_view = 0;
472  break;
473  }
474 
475  len = WPRINTF_GetLen( &format, &argData, number, maxlen - 1 );
476  sign = 0;
477  if (!(format.flags & WPRINTF_LEFTALIGN))
478  for (i = format.precision; i < format.width; i++, maxlen--)
479  *p++ = ' ';
480  switch(format.type)
481  {
482  case WPR_WCHAR:
483  *p++ = argData.wchar_view;
484  break;
485  case WPR_CHAR:
486  *p++ = argData.char_view;
487  break;
488  case WPR_STRING:
489  {
490  LPCSTR ptr = argData.lpcstr_view;
491  for (i = 0; i < len; i++) *p++ = (BYTE)*ptr++;
492  }
493  break;
494  case WPR_WSTRING:
495  if (len) memcpy( p, argData.lpcwstr_view, len * sizeof(WCHAR) );
496  p += len;
497  break;
498  case WPR_HEXA:
499  if ((format.flags & WPRINTF_PREFIX_HEX) && (maxlen > 3))
500  {
501  *p++ = '0';
502  *p++ = (format.flags & WPRINTF_UPPER_HEX) ? 'X' : 'x';
503  maxlen -= 2;
504  len -= 2;
505  }
506  /* fall through */
507  case WPR_SIGNED:
508  /* Transfer the sign now, just in case it will be zero-padded*/
509  if (number[0] == '-')
510  {
511  *p++ = '-';
512  sign = 1;
513  }
514  /* fall through */
515  case WPR_UNSIGNED:
516  for (i = len; i < format.precision; i++, maxlen--) *p++ = '0';
517  for (i = sign; i < len; i++) *p++ = (BYTE)number[i];
518  break;
519  case WPR_UNKNOWN:
520  continue;
521  }
522  if (format.flags & WPRINTF_LEFTALIGN)
523  for (i = format.precision; i < format.width; i++, maxlen--)
524  *p++ = ' ';
525  maxlen -= len;
526  }
527  *p = 0;
528  TRACE("%s\n",debugstr_w(buffer));
529  return (maxlen > 1) ? (INT)(p - buffer) : -1;
530 }
531 
532 
533 /*************************************************************************
534  * wnsprintfA (SHLWAPI.@)
535  *
536  * Print formatted output to a string, up to a maximum number of chars.
537  *
538  * PARAMS
539  * lpOut [O] Destination for output string
540  * cchLimitIn [I] Maximum number of characters to write
541  * lpFmt [I] Format string
542  *
543  * RETURNS
544  * Success: The number of characters written.
545  * Failure: -1.
546  */
547 int WINAPIV wnsprintfA(LPSTR lpOut, int cchLimitIn, LPCSTR lpFmt, ...)
548 {
550  INT res;
551 
552  __ms_va_start( valist, lpFmt );
553  res = wvnsprintfA( lpOut, cchLimitIn, lpFmt, valist );
554  __ms_va_end( valist );
555  return res;
556 }
557 
558 
559 /*************************************************************************
560  * wnsprintfW (SHLWAPI.@)
561  *
562  * See wnsprintfA.
563  */
564 int WINAPIV wnsprintfW(LPWSTR lpOut, int cchLimitIn, LPCWSTR lpFmt, ...)
565 {
567  INT res;
568 
569  __ms_va_start( valist, lpFmt );
570  res = wvnsprintfW( lpOut, cchLimitIn, lpFmt, valist );
571  __ms_va_end( valist );
572  return res;
573 }
static size_t double int int int * sign
Definition: printf.c:64
unsigned __int3264 UINT_PTR
Definition: activex.cpp:275
static const char __ms_va_list
Definition: printf.c:70
UINT precision
Definition: wsprintf.c:65
const char * res
Definition: wsprintf.c:32
__wchar_t WCHAR
Definition: xmlstorage.h:180
char CHAR
Definition: xmlstorage.h:175
CHAR char_view
Definition: wsprintf.c:71
static INT WPRINTF_ParseFormatW(LPCWSTR format, WPRINTF_FORMAT *res)
Definition: wsprintf.c:171
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
GLuint buffer
Definition: glext.h:5915
WINE_DEFAULT_DEBUG_CHANNEL(string)
static INT WPRINTF_ParseFormatA(LPCSTR format, WPRINTF_FORMAT *res)
Definition: wsprintf.c:89
#define WPRINTF_PREFIX_HEX
Definition: wsprintf.c:40
INT WINAPI wvnsprintfW(LPWSTR buffer, INT maxlen, LPCWSTR spec, __ms_va_list args)
Definition: wsprintf.c:432
int32_t INT_PTR
Definition: typedefs.h:62
char * LPSTR
Definition: xmlstorage.h:182
#define WCHAR
Definition: msvc.h:43
Definition: match.c:390
int32_t INT
Definition: typedefs.h:56
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl.h:1546
LPCWSTR lpcwstr_view
Definition: wsprintf.c:73
LONGLONG int_view
Definition: wsprintf.c:74
const XML_Char int const XML_Char int const XML_Char * base
Definition: expat.h:331
GLenum GLclampf GLint i
Definition: glfuncs.h:14
static size_t double number
Definition: printf.c:64
#define debugstr_w
Definition: kernel32.h:32
static PVOID ptr
Definition: dispmode.c:27
#define INT(a)
Definition: assyntax.h:463
#define WPRINTF_LONG
Definition: wsprintf.c:42
const char * LPCSTR
Definition: xmlstorage.h:183
WPRINTF_TYPE type
Definition: wsprintf.c:66
int64_t LONGLONG
Definition: typedefs.h:66
#define TRACE(s)
Definition: solgame.cpp:4
#define WPRINTF_I64
Definition: wsprintf.c:47
#define debugstr_a
Definition: kernel32.h:31
uint64_t ULONGLONG
Definition: typedefs.h:65
GLuint GLuint num
Definition: glext.h:9618
#define WPRINTF_INTPTR
Definition: wsprintf.c:46
#define WPRINTF_LEFTALIGN
Definition: wsprintf.c:39
int WINAPIV wnsprintfA(LPSTR lpOut, int cchLimitIn, LPCSTR lpFmt,...)
Definition: wsprintf.c:547
static const WCHAR null_stringW[]
Definition: wsprintf.c:78
static const CHAR null_stringA[]
Definition: wsprintf.c:77
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define WPRINTF_ZEROPAD
Definition: wsprintf.c:41
GLenum GLsizei len
Definition: glext.h:6722
int WINAPIV wnsprintfW(LPWSTR lpOut, int cchLimitIn, LPCWSTR lpFmt,...)
Definition: wsprintf.c:564
#define WINAPI
Definition: msvc.h:20
#define WINAPIV
Definition: sdbpapi.h:64
unsigned char BYTE
Definition: ntddk_ex.h:96
#define WPRINTF_WIDE
Definition: wsprintf.c:45
#define va_arg(ap, T)
Definition: acmsvcex.h:89
LPCSTR lpcstr_view
Definition: wsprintf.c:72
#define WPRINTF_UPPER_HEX
Definition: wsprintf.c:44
WPRINTF_TYPE
Definition: wsprintf.c:49
unsigned int UINT
Definition: ndis.h:50
#define __ms_va_end(list)
Definition: windef.h:448
GLuint const GLubyte GLvoid const GLvoid * dst
Definition: s_context.h:57
static UINT WPRINTF_GetLen(WPRINTF_FORMAT *format, WPRINTF_DATA *arg, LPSTR number, UINT maxlen)
Definition: wsprintf.c:247
#define __ms_va_start(list, arg)
Definition: windef.h:447
GLuint res
Definition: glext.h:9613
WCHAR wchar_view
Definition: wsprintf.c:70
static __ms_va_list valist
Definition: printf.c:59
#define WPRINTF_SHORT
Definition: wsprintf.c:43
GLfloat GLfloat p
Definition: glext.h:8902
INT WINAPI wvnsprintfA(LPSTR buffer, INT maxlen, LPCSTR spec, __ms_va_list args)
Definition: wsprintf.c:325
WCHAR * LPWSTR
Definition: xmlstorage.h:184
#define CHAR(Char)
static const int digits[]
Definition: decode.c:71