1 /* $Id: swprintf.c,v 1.7 2002/09/08 10:23:42 chorns Exp $
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 * - Implement maximum length (cnt) in _vsnwprintf().
12 * - Verify the implementation of '%Z'.
16 * linux/lib/vsprintf.c
18 * Copyright (C) 1991, 1992 Linus Torvalds
21 /* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
23 * Wirzenius wrote this portably, Torvalds fucked it up :-)
26 #include <ddk/ntddk.h>
34 #include <internal/debug.h>
37 #define ZEROPAD 1 /* pad with zero */
38 #define SIGN 2 /* unsigned/signed long */
39 #define PLUS 4 /* show plus */
40 #define SPACE 8 /* space if plus */
41 #define LEFT 16 /* left justified */
42 #define SPECIAL 32 /* 0x */
43 #define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
46 #define do_div(n,base) ({ \
48 __res = ((unsigned long long) n) % (unsigned) base; \
49 n = ((unsigned long long) n) / (unsigned) base; \
53 static int skip_atoi(const wchar_t **s
)
58 i
= i
*10 + *((*s
)++) - L
'0';
64 number (wchar_t *str
, long long num
, int base
, int size
, int precision
,
67 wchar_t c
,sign
,tmp
[66];
68 const wchar_t *digits
= L
"0123456789abcdefghijklmnopqrstuvwxyz";
72 digits
= L
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
75 if (base
< 2 || base
> 36)
78 c
= (type
& ZEROPAD
) ? L
'0' : L
' ';
94 else if (type
& SPACE
)
112 else while (num
!= 0)
113 tmp
[i
++] = digits
[do_div(num
,base
)];
117 if (!(type
&(ZEROPAD
+LEFT
)))
137 while (i
< precision
--)
147 int _vsnwprintf(wchar_t *buf
, size_t cnt
, const wchar_t *fmt
, va_list args
)
150 unsigned long long num
;
156 int flags
; /* flags to number() */
158 int field_width
; /* width of output field */
159 int precision
; /* min. # of digits for integers; max
160 number of chars for from string */
161 int qualifier
; /* 'h', 'l', 'L', 'w' or 'I' for integer fields */
163 for (str
=buf
; *fmt
; ++fmt
) {
172 ++fmt
; /* this also skips first '%' */
174 case L
'-': flags
|= LEFT
; goto repeat
;
175 case L
'+': flags
|= PLUS
; goto repeat
;
176 case L
' ': flags
|= SPACE
; goto repeat
;
177 case L
'#': flags
|= SPECIAL
; goto repeat
;
178 case L
'0': flags
|= ZEROPAD
; goto repeat
;
181 /* get field width */
184 field_width
= skip_atoi(&fmt
);
185 else if (*fmt
== L
'*') {
187 /* it's the next argument */
188 field_width
= va_arg(args
, int);
189 if (field_width
< 0) {
190 field_width
= -field_width
;
195 /* get the precision */
200 precision
= skip_atoi(&fmt
);
201 else if (*fmt
== L
'*') {
203 /* it's the next argument */
204 precision
= va_arg(args
, int);
210 /* get the conversion qualifier */
212 if (*fmt
== 'h' || *fmt
== 'l' || *fmt
== 'L' || *fmt
== 'w') {
215 } else if (*fmt
== 'I' && *(fmt
+1) == '6' && *(fmt
+2) == '4') {
226 while (--field_width
> 0)
228 if (qualifier
== 'h')
229 *str
++ = (wchar_t) va_arg(args
, int);
231 *str
++ = (wchar_t) va_arg(args
, int);
232 while (--field_width
> 0)
238 while (--field_width
> 0)
240 if (qualifier
== 'l' || qualifier
== 'w')
241 *str
++ = (wchar_t) va_arg(args
, int);
243 *str
++ = (wchar_t) va_arg(args
, int);
244 while (--field_width
> 0)
249 if (qualifier
== 'h') {
250 /* print ascii string */
251 s
= va_arg(args
, char *);
256 if ((unsigned int)len
> (unsigned int)precision
)
260 while (len
< field_width
--)
262 for (i
= 0; i
< len
; ++i
)
263 *str
++ = (wchar_t)(*s
++);
264 while (len
< field_width
--)
267 /* print unicode string */
268 sw
= va_arg(args
, wchar_t *);
273 if ((unsigned int)len
> (unsigned int)precision
)
277 while (len
< field_width
--)
279 for (i
= 0; i
< len
; ++i
)
281 while (len
< field_width
--)
287 if (qualifier
== 'l' || qualifier
== 'w') {
288 /* print unicode string */
289 sw
= va_arg(args
, wchar_t *);
294 if ((unsigned int)len
> (unsigned int)precision
)
298 while (len
< field_width
--)
300 for (i
= 0; i
< len
; ++i
)
302 while (len
< field_width
--)
305 /* print ascii string */
306 s
= va_arg(args
, char *);
311 if ((unsigned int)len
> (unsigned int)precision
)
315 while (len
< field_width
--)
317 for (i
= 0; i
< len
; ++i
)
318 *str
++ = (wchar_t)(*s
++);
319 while (len
< field_width
--)
325 if (qualifier
== 'h') {
326 /* print counted ascii string */
327 PANSI_STRING pus
= va_arg(args
, PANSI_STRING
);
328 if ((pus
== NULL
) || (pus
->Buffer
== NULL
)) {
333 for (i
= 0; pus
->Buffer
[i
] && i
< pus
->Length
; i
++)
334 *str
++ = (wchar_t)(pus
->Buffer
[i
]);
337 /* print counted unicode string */
338 PUNICODE_STRING pus
= va_arg(args
, PUNICODE_STRING
);
339 if ((pus
== NULL
) || (pus
->Buffer
== NULL
)) {
344 for (i
= 0; pus
->Buffer
[i
] && i
< pus
->Length
/ sizeof(WCHAR
); i
++)
345 *str
++ = pus
->Buffer
[i
];
351 if (field_width
== -1) {
352 field_width
= 2*sizeof(void *);
356 (unsigned long) va_arg(args
, void *), 16,
357 field_width
, precision
, flags
);
361 if (qualifier
== 'l') {
362 long * ip
= va_arg(args
, long *);
365 int * ip
= va_arg(args
, int *);
370 /* integer number formats - set up the flags and "break" */
401 if (qualifier
== 'I')
402 num
= va_arg(args
, unsigned long long);
403 else if (qualifier
== 'l')
404 num
= va_arg(args
, unsigned long);
405 else if (qualifier
== 'h') {
407 num
= va_arg(args
, int);
409 num
= va_arg(args
, unsigned int);
413 num
= va_arg(args
, int);
415 num
= va_arg(args
, unsigned int);
417 str
= number(str
, num
, base
, field_width
, precision
, flags
);
424 int swprintf(wchar_t *buf
, const wchar_t *fmt
, ...)
430 i
=_vsnwprintf(buf
,INT_MAX
,fmt
,args
);
436 int _snwprintf(wchar_t *buf
, size_t cnt
, const wchar_t *fmt
, ...)
442 i
=_vsnwprintf(buf
,cnt
,fmt
,args
);
448 int vswprintf(wchar_t *buf
, const wchar_t *fmt
, va_list args
)
450 return _vsnwprintf(buf
,INT_MAX
,fmt
,args
);