3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/rtl/swprintf.c
6 * PURPOSE: unicode sprintf functions
7 * PROGRAMMERS: David Welch
11 * - Verify the implementation of '%Z'.
15 * linux/lib/vsprintf.c
17 * Copyright (C) 1991, 1992 Linus Torvalds
20 /* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
22 * Wirzenius wrote this portably, Torvalds fucked it up :-)
26 #include <internal/ctype.h>
28 #include <internal/debug.h>
32 typedef long long SWPRINT_INT64
;
33 typedef unsigned long long SWPRINT_UINT64
;
35 typedef __int64 SWPRINT_INT64
;
36 typedef unsigned __int64 SWPRINT_UINT64
;
40 #define ZEROPAD 1 /* pad with zero */
41 #define SIGN 2 /* unsigned/signed long */
42 #define PLUS 4 /* show plus */
43 #define SPACE 8 /* space if plus */
44 #define LEFT 16 /* left justified */
45 #define SPECIAL 32 /* 0x */
46 #define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
51 #define do_div(n,base) ({ \
53 __res = ((SWPRINT_UINT64) n) % (unsigned) base; \
54 n = ((SWPRINT_UINT64) n) / (unsigned) base; \
57 #elif defined(_MSC_VER)
59 static __inline
int do_foo_div(SWPRINT_INT64
* n
, int base
)
61 int __res
= (int)(((SWPRINT_UINT64
) *n
) % (unsigned) base
);
62 *n
= (int)(((SWPRINT_UINT64
) *n
) / (unsigned) base
);
65 #define do_div(n,base) do_foo_div(&n,base)
68 #error Unknown compiler for this special compiler trickery
73 static int skip_atoi(const wchar_t **s
)
78 i
= i
*10 + *((*s
)++) - L
'0';
84 number(wchar_t * buf
, wchar_t * end
, SWPRINT_INT64 num
, int base
, int size
, int precision
, int type
)
86 wchar_t c
,sign
, tmp
[66];
87 const wchar_t *digits
;
88 const wchar_t *small_digits
= L
"0123456789abcdefghijklmnopqrstuvwxyz";
89 const wchar_t *large_digits
= L
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
92 digits
= (type
& LARGE
) ? large_digits
: small_digits
;
95 if (base
< 2 || base
> 36)
97 c
= (type
& ZEROPAD
) ? L
'0' : L
' ';
104 } else if (type
& PLUS
) {
107 } else if (type
& SPACE
) {
112 if (type
& SPECIAL
) {
121 else while (num
!= 0)
122 tmp
[i
++] = digits
[do_div(num
,base
)];
126 if (!(type
&(ZEROPAD
+LEFT
))) {
138 if (type
& SPECIAL
) {
143 } else if (base
==16) {
152 if (!(type
& LEFT
)) {
159 while (i
< precision
--) {
178 string(wchar_t* buf
, wchar_t* end
, const char* s
, int len
, int field_width
, int precision
, int flags
)
191 while ((unsigned int)len
< (unsigned int)precision
&& s
[len
])
196 if ((unsigned int)len
> (unsigned int)precision
)
201 while (len
< field_width
--)
207 for (i
= 0; i
< len
; ++i
)
213 while (len
< field_width
--)
223 stringw(wchar_t* buf
, wchar_t* end
, const wchar_t* sw
, int len
, int field_width
, int precision
, int flags
)
236 while ((unsigned int)len
< (unsigned int)precision
&& sw
[len
])
241 if ((unsigned int)len
> (unsigned int)precision
)
246 while (len
< field_width
--)
252 for (i
= 0; i
< len
; ++i
)
258 while (len
< field_width
--)
267 int _vsnwprintf(wchar_t *buf
, size_t cnt
, const wchar_t *fmt
, va_list args
)
272 wchar_t * str
, * end
;
276 int flags
; /* flags to number() */
278 int field_width
; /* width of output field */
279 int precision
; /* min. # of digits for integers; max
280 number of chars for from string */
281 int qualifier
; /* 'h', 'l', 'L', 'w' or 'I' for integer fields */
290 for ( ; *fmt
; ++fmt
) {
301 ++fmt
; /* this also skips first '%' */
303 case L
'-': flags
|= LEFT
; goto repeat
;
304 case L
'+': flags
|= PLUS
; goto repeat
;
305 case L
' ': flags
|= SPACE
; goto repeat
;
306 case L
'#': flags
|= SPECIAL
; goto repeat
;
307 case L
'0': flags
|= ZEROPAD
; goto repeat
;
310 /* get field width */
313 field_width
= skip_atoi(&fmt
);
314 else if (*fmt
== L
'*') {
316 /* it's the next argument */
317 field_width
= va_arg(args
, int);
318 if (field_width
< 0) {
319 field_width
= -field_width
;
324 /* get the precision */
329 precision
= skip_atoi(&fmt
);
330 else if (*fmt
== L
'*') {
332 /* it's the next argument */
333 precision
= va_arg(args
, int);
339 /* get the conversion qualifier */
341 if (*fmt
== L
'h' || *fmt
== L
'l' || *fmt
== L
'L' || *fmt
== L
'w') {
344 } else if (*fmt
== L
'I' && *(fmt
+1) == L
'6' && *(fmt
+2) == L
'4') {
355 while (--field_width
> 0) {
360 if (qualifier
== 'h') {
362 *str
= (wchar_t) va_arg(args
, int);
366 *str
= (wchar_t) va_arg(args
, int);
369 while (--field_width
> 0) {
378 while (--field_width
> 0) {
383 if (qualifier
== 'l' || qualifier
== 'w') {
385 *str
= (wchar_t) va_arg(args
, int);
389 *str
= (wchar_t) va_arg(args
, int);
392 while (--field_width
> 0) {
400 if (qualifier
== 'h') {
401 /* print ascii string */
402 s
= va_arg(args
, char *);
403 str
= string(str
, end
, s
, -1, field_width
, precision
, flags
);
405 /* print unicode string */
406 sw
= va_arg(args
, wchar_t *);
407 str
= stringw(str
, end
, sw
, -1, field_width
, precision
, flags
);
412 if (qualifier
== 'l' || qualifier
== 'w') {
413 /* print unicode string */
414 sw
= va_arg(args
, wchar_t *);
415 str
= stringw(str
, end
, sw
, -1, field_width
, precision
, flags
);
417 /* print ascii string */
418 s
= va_arg(args
, char *);
419 str
= string(str
, end
, s
, -1, field_width
, precision
, flags
);
424 if (qualifier
== 'h') {
425 /* print counted ascii string */
426 PANSI_STRING pus
= va_arg(args
, PANSI_STRING
);
427 if ((pus
== NULL
) || (pus
->Buffer
== NULL
)) {
434 str
= string(str
, end
, s
, len
, field_width
, precision
, flags
);
436 /* print counted unicode string */
437 PUNICODE_STRING pus
= va_arg(args
, PUNICODE_STRING
);
438 if ((pus
== NULL
) || (pus
->Buffer
== NULL
)) {
443 len
= pus
->Length
/ sizeof(WCHAR
);
445 str
= stringw(str
, end
, sw
, len
, field_width
, precision
, flags
);
450 if (field_width
== -1) {
451 field_width
= 2*sizeof(void *);
454 str
= number(str
, end
,
455 (unsigned long) va_arg(args
, void *), 16,
456 field_width
, precision
, flags
);
460 /* FIXME: What does C99 say about the overflow case here? */
461 if (qualifier
== 'l') {
462 long * ip
= va_arg(args
, long *);
465 int * ip
= va_arg(args
, int *);
470 /* integer number formats - set up the flags and "break" */
506 if (qualifier
== L
'I')
507 num
= va_arg(args
, SWPRINT_UINT64
);
508 else if (qualifier
== L
'l') {
510 num
= va_arg(args
, long);
512 num
= va_arg(args
, unsigned long);
514 else if (qualifier
== L
'h') {
516 num
= va_arg(args
, int);
518 num
= va_arg(args
, unsigned int);
522 num
= va_arg(args
, int);
524 num
= va_arg(args
, unsigned int);
526 str
= number(str
, end
, num
, base
, field_width
, precision
, flags
);
531 /* don't write out a null byte if the buf size is zero */
540 int swprintf(wchar_t *buf
, const wchar_t *fmt
, ...)
546 i
=_vsnwprintf(buf
,INT_MAX
,fmt
,args
);
555 int _snwprintf(wchar_t *buf
, size_t cnt
, const wchar_t *fmt
, ...)
561 i
=_vsnwprintf(buf
,cnt
,fmt
,args
);
567 int vswprintf(wchar_t *buf
, const wchar_t *fmt
, va_list args
)
569 return _vsnwprintf(buf
,INT_MAX
,fmt
,args
);