3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/rtl/swprintf.c
6 * PURPOSE: Unicode sprintf functions
8 * PROGRAMMERS: David Welch
14 * - Verify the implementation of '%Z'.
18 * linux/lib/vsprintf.c
20 * Copyright (C) 1991, 1992 Linus Torvalds
23 /* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
25 * Wirzenius wrote this portably, Torvalds fucked it up :-)
29 #include <internal/ctype.h>
31 #include <internal/debug.h>
35 typedef long long SWPRINT_INT64
;
36 typedef unsigned long long SWPRINT_UINT64
;
38 typedef __int64 SWPRINT_INT64
;
39 typedef unsigned __int64 SWPRINT_UINT64
;
43 #define ZEROPAD 1 /* pad with zero */
44 #define SIGN 2 /* unsigned/signed long */
45 #define PLUS 4 /* show plus */
46 #define SPACE 8 /* space if plus */
47 #define LEFT 16 /* left justified */
48 #define SPECIAL 32 /* 0x */
49 #define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
54 #define do_div(n,base) ({ \
56 __res = ((SWPRINT_UINT64) n) % (unsigned) base; \
57 n = ((SWPRINT_UINT64) n) / (unsigned) base; \
60 #elif defined(_MSC_VER)
62 static __inline
int do_foo_div(SWPRINT_INT64
* n
, int base
)
64 int __res
= (int)(((SWPRINT_UINT64
) *n
) % (unsigned) base
);
65 *n
= (int)(((SWPRINT_UINT64
) *n
) / (unsigned) base
);
68 #define do_div(n,base) do_foo_div(&n,base)
71 #error Unknown compiler for this special compiler trickery
76 static int skip_atoi(const wchar_t **s
)
81 i
= i
*10 + *((*s
)++) - L
'0';
87 number(wchar_t * buf
, wchar_t * end
, SWPRINT_INT64 num
, int base
, int size
, int precision
, int type
)
89 wchar_t c
,sign
, tmp
[66];
90 const wchar_t *digits
;
91 const wchar_t *small_digits
= L
"0123456789abcdefghijklmnopqrstuvwxyz";
92 const wchar_t *large_digits
= L
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
95 digits
= (type
& LARGE
) ? large_digits
: small_digits
;
98 if (base
< 2 || base
> 36)
100 c
= (type
& ZEROPAD
) ? L
'0' : L
' ';
107 } else if (type
& PLUS
) {
110 } else if (type
& SPACE
) {
115 if (type
& SPECIAL
) {
124 else while (num
!= 0)
125 tmp
[i
++] = digits
[do_div(num
,base
)];
129 if (!(type
&(ZEROPAD
+LEFT
))) {
141 if (type
& SPECIAL
) {
146 } else if (base
==16) {
155 if (!(type
& LEFT
)) {
162 while (i
< precision
--) {
181 string(wchar_t* buf
, wchar_t* end
, const char* s
, int len
, int field_width
, int precision
, int flags
)
194 while ((unsigned int)len
< (unsigned int)precision
&& s
[len
])
199 if ((unsigned int)len
> (unsigned int)precision
)
204 while (len
< field_width
--)
210 for (i
= 0; i
< len
; ++i
)
216 while (len
< field_width
--)
226 stringw(wchar_t* buf
, wchar_t* end
, const wchar_t* sw
, int len
, int field_width
, int precision
, int flags
)
239 while ((unsigned int)len
< (unsigned int)precision
&& sw
[len
])
244 if ((unsigned int)len
> (unsigned int)precision
)
249 while (len
< field_width
--)
255 for (i
= 0; i
< len
; ++i
)
261 while (len
< field_width
--)
270 int _vsnwprintf(wchar_t *buf
, size_t cnt
, const wchar_t *fmt
, va_list args
)
275 wchar_t * str
, * end
;
279 int flags
; /* flags to number() */
281 int field_width
; /* width of output field */
282 int precision
; /* min. # of digits for integers; max
283 number of chars for from string */
284 int qualifier
; /* 'h', 'l', 'L', 'w' or 'I' for integer fields */
293 for ( ; *fmt
; ++fmt
) {
304 ++fmt
; /* this also skips first '%' */
306 case L
'-': flags
|= LEFT
; goto repeat
;
307 case L
'+': flags
|= PLUS
; goto repeat
;
308 case L
' ': flags
|= SPACE
; goto repeat
;
309 case L
'#': flags
|= SPECIAL
; goto repeat
;
310 case L
'0': flags
|= ZEROPAD
; goto repeat
;
313 /* get field width */
316 field_width
= skip_atoi(&fmt
);
317 else if (*fmt
== L
'*') {
319 /* it's the next argument */
320 field_width
= va_arg(args
, int);
321 if (field_width
< 0) {
322 field_width
= -field_width
;
327 /* get the precision */
332 precision
= skip_atoi(&fmt
);
333 else if (*fmt
== L
'*') {
335 /* it's the next argument */
336 precision
= va_arg(args
, int);
342 /* get the conversion qualifier */
344 if (*fmt
== L
'h' || *fmt
== L
'l' || *fmt
== L
'L' || *fmt
== L
'w') {
347 } else if (*fmt
== L
'I' && *(fmt
+1) == L
'6' && *(fmt
+2) == L
'4') {
358 while (--field_width
> 0) {
363 if (qualifier
== 'h') {
365 *str
= (wchar_t) va_arg(args
, int);
369 *str
= (wchar_t) va_arg(args
, int);
372 while (--field_width
> 0) {
381 while (--field_width
> 0) {
386 if (qualifier
== 'l' || qualifier
== 'w') {
388 *str
= (wchar_t) va_arg(args
, int);
392 *str
= (wchar_t) va_arg(args
, int);
395 while (--field_width
> 0) {
403 if (qualifier
== 'h') {
404 /* print ascii string */
405 s
= va_arg(args
, char *);
406 str
= string(str
, end
, s
, -1, field_width
, precision
, flags
);
408 /* print unicode string */
409 sw
= va_arg(args
, wchar_t *);
410 str
= stringw(str
, end
, sw
, -1, field_width
, precision
, flags
);
415 if (qualifier
== 'l' || qualifier
== 'w') {
416 /* print unicode string */
417 sw
= va_arg(args
, wchar_t *);
418 str
= stringw(str
, end
, sw
, -1, field_width
, precision
, flags
);
420 /* print ascii string */
421 s
= va_arg(args
, char *);
422 str
= string(str
, end
, s
, -1, field_width
, precision
, flags
);
427 if (qualifier
== 'h') {
428 /* print counted ascii string */
429 PANSI_STRING pus
= va_arg(args
, PANSI_STRING
);
430 if ((pus
== NULL
) || (pus
->Buffer
== NULL
)) {
437 str
= string(str
, end
, s
, len
, field_width
, precision
, flags
);
439 /* print counted unicode string */
440 PUNICODE_STRING pus
= va_arg(args
, PUNICODE_STRING
);
441 if ((pus
== NULL
) || (pus
->Buffer
== NULL
)) {
446 len
= pus
->Length
/ sizeof(WCHAR
);
448 str
= stringw(str
, end
, sw
, len
, field_width
, precision
, flags
);
453 if (field_width
== -1) {
454 field_width
= 2*sizeof(void *);
457 str
= number(str
, end
,
458 (unsigned long) va_arg(args
, void *), 16,
459 field_width
, precision
, flags
);
463 /* FIXME: What does C99 say about the overflow case here? */
464 if (qualifier
== 'l') {
465 long * ip
= va_arg(args
, long *);
468 int * ip
= va_arg(args
, int *);
473 /* integer number formats - set up the flags and "break" */
509 if (qualifier
== L
'I')
510 num
= va_arg(args
, SWPRINT_UINT64
);
511 else if (qualifier
== L
'l') {
513 num
= va_arg(args
, long);
515 num
= va_arg(args
, unsigned long);
517 else if (qualifier
== L
'h') {
519 num
= va_arg(args
, int);
521 num
= va_arg(args
, unsigned int);
525 num
= va_arg(args
, int);
527 num
= va_arg(args
, unsigned int);
529 str
= number(str
, end
, num
, base
, field_width
, precision
, flags
);
534 /* don't write out a null byte if the buf size is zero */
543 int swprintf(wchar_t *buf
, const wchar_t *fmt
, ...)
549 i
=_vsnwprintf(buf
,INT_MAX
,fmt
,args
);
558 int _snwprintf(wchar_t *buf
, size_t cnt
, const wchar_t *fmt
, ...)
564 i
=_vsnwprintf(buf
,cnt
,fmt
,args
);
570 int vswprintf(wchar_t *buf
, const wchar_t *fmt
, va_list args
)
572 return _vsnwprintf(buf
,INT_MAX
,fmt
,args
);