2 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Copyright 2003-2008, Axel Dörfler. All rights reserved.
4 * Distributed under the terms of the MIT license.
6 * Copyright 2001, Travis Geiselbrecht. All rights reserved.
7 * Distributed under the terms of the NewOS License.
11 #include <SupportDefs.h>
21 #define ZEROPAD 1 /* pad with zero */
22 #define SIGN 2 /* unsigned/signed long */
23 #define PLUS 4 /* show plus */
24 #define SPACE 8 /* space if plus */
25 #define LEFT 16 /* left justified */
26 #define SPECIAL 32 /* 0x */
27 #define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
29 #define FLOATING_SUPPORT
33 Buffer(char* buffer
, size_t size
)
41 size_t BytesWritten() const
46 void PutCharacter(char c
)
48 if (fBytesWritten
< fSize
) {
56 void PutPadding(int32 count
)
61 if (fBytesWritten
< fSize
) {
62 int32 toWrite
= std::min(fSize
- fBytesWritten
, (size_t)count
);
63 while (--toWrite
>= 0)
67 fBytesWritten
+= count
;
70 void PutString(const char *source
, int32 length
)
75 if (fBytesWritten
< fSize
) {
76 int32 toWrite
= std::min(fSize
- fBytesWritten
, (size_t)length
);
77 memcpy(fCurrent
, source
, toWrite
);
81 fBytesWritten
+= length
;
86 if (fBytesWritten
< fSize
)
100 skip_atoi(const char **s
)
105 i
= i
*10 + *((*s
)++) - '0';
112 do_div(uint64
*_number
, uint32 base
)
114 uint64 result
= *_number
% (uint64
)base
;
115 *_number
= *_number
/ (uint64
)base
;
122 sign_symbol(int flags
, bool negative
)
124 if ((flags
& SIGN
) == 0)
129 else if ((flags
& PLUS
) != 0)
131 else if ((flags
& SPACE
) != 0)
139 number(Buffer
& outBuffer
, uint64 num
, uint32 base
, int size
,
140 int precision
, int flags
)
142 const char *digits
= "0123456789abcdefghijklmnopqrstuvwxyz";
143 char c
, sign
, tmp
[66];
147 digits
= "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
150 if (base
< 2 || base
> 36)
153 c
= (flags
& ZEROPAD
) ? '0' : ' ';
156 sign
= sign_symbol(flags
, (int64
)num
< 0);
164 if ((flags
& SPECIAL
) != 0) {
174 else while (num
!= 0)
175 tmp
[i
++] = digits
[do_div(&num
, base
)];
181 if (!(flags
& (ZEROPAD
+ LEFT
))) {
182 outBuffer
.PutPadding(size
);
186 outBuffer
.PutCharacter(sign
);
188 if ((flags
& SPECIAL
) != 0) {
190 outBuffer
.PutCharacter('0');
191 else if (base
== 16) {
192 outBuffer
.PutCharacter('0');
193 outBuffer
.PutCharacter(digits
[33]);
197 if (!(flags
& LEFT
)) {
199 outBuffer
.PutCharacter(c
);
201 while (i
< precision
--)
202 outBuffer
.PutCharacter('0');
204 outBuffer
.PutCharacter(tmp
[i
]);
206 outBuffer
.PutPadding(size
);
210 #ifdef FLOATING_SUPPORT
212 This is a very basic floating point to string conversion routine.
213 It prints up to 3 fraction digits, and doesn't support any precision arguments.
214 It's just here for your convenience so that you can use it for debug output.
217 floating(Buffer
& outBuffer
, double value
, int fieldWidth
, int flags
)
225 sign
= sign_symbol(flags
, value
< 0.0);
229 fraction
= (uint64
)(value
* 1000) % 1000;
230 integer
= (uint64
)value
;
232 // put fraction part, if any
236 while (fraction
!= 0) {
237 int digit
= do_div(&fraction
, 10);
238 if (!first
|| digit
> 0) {
239 buffer
[length
++] = '0' + digit
;
244 buffer
[length
++] = '.';
250 buffer
[length
++] = '0';
253 buffer
[length
++] = '0' + do_div(&integer
, 10);
256 // write back to string
259 outBuffer
.PutPadding(fieldWidth
);
262 outBuffer
.PutCharacter(sign
);
265 outBuffer
.PutCharacter(buffer
[length
]);
267 if ((flags
& LEFT
) != 0)
268 outBuffer
.PutPadding(fieldWidth
);
270 #endif // FLOATING_SUPPORT
274 vsnprintf(char *buffer
, size_t bufferSize
, const char *format
, va_list args
)
278 int flags
; /* flags to number() */
279 int fieldWidth
; /* width of output field */
281 /* min. # of digits for integers; max number of chars for from string */
282 int qualifier
; /* 'h', 'l', or 'L' for integer fields */
284 Buffer
outBuffer(buffer
, bufferSize
);
286 for (; format
[0]; format
++) {
287 if (format
[0] != '%') {
288 outBuffer
.PutCharacter(format
[0]);
298 /* this also skips first '%' */
300 case '-': flags
|= LEFT
; goto repeat
;
301 case '+': flags
|= PLUS
; goto repeat
;
302 case ' ': flags
|= SPACE
; goto repeat
;
303 case '#': flags
|= SPECIAL
; goto repeat
;
304 case '0': flags
|= ZEROPAD
; goto repeat
;
307 outBuffer
.PutCharacter(format
[0]);
311 /* get field width */
314 if (isdigit(*format
))
315 fieldWidth
= skip_atoi(&format
);
316 else if (format
[0] == '*') {
318 /* it's the next argument */
319 fieldWidth
= va_arg(args
, int);
320 if (fieldWidth
< 0) {
321 fieldWidth
= -fieldWidth
;
326 /* get the precision */
329 if (format
[0] == '.') {
331 if (isdigit(*format
))
332 precision
= skip_atoi(&format
);
333 else if (format
[0] == '*') {
335 /* it's the next argument */
336 precision
= va_arg(args
, int);
342 /* get the conversion qualifier */
345 if (format
[0] == 'h' || format
[0] == 'L' || format
[0] == 'z') {
346 qualifier
= *format
++;
347 } else if (format
[0] == 'l') {
349 if (format
[0] == 'l') {
362 outBuffer
.PutPadding(fieldWidth
- 1);
364 outBuffer
.PutCharacter((char)va_arg(args
, int));
366 if ((flags
& LEFT
) != 0)
367 outBuffer
.PutPadding(fieldWidth
- 1);
372 const char *argument
= va_arg(args
, char *);
375 if (argument
== NULL
)
378 length
= strnlen(argument
, precision
);
379 fieldWidth
-= length
;
382 outBuffer
.PutPadding(fieldWidth
);
384 outBuffer
.PutString(argument
, length
);
386 if ((flags
& LEFT
) != 0)
387 outBuffer
.PutPadding(fieldWidth
);
391 #ifdef FLOATING_SUPPORT
397 double value
= va_arg(args
, double);
398 floating(outBuffer
, value
, fieldWidth
, flags
| SIGN
);
401 #endif // FLOATING_SUPPORT
404 if (fieldWidth
== -1) {
405 fieldWidth
= 2*sizeof(void *);
409 outBuffer
.PutString("0x", 2);
410 number(outBuffer
, (addr_t
)va_arg(args
, void *), 16, fieldWidth
,
415 if (qualifier
== 'l') {
416 long *ip
= va_arg(args
, long *);
417 *ip
= outBuffer
.BytesWritten();
419 int *ip
= va_arg(args
, int *);
420 *ip
= outBuffer
.BytesWritten();
424 /* integer number formats - set up the flags and "break" */
442 if (format
[0] != '%')
443 outBuffer
.PutCharacter('%');
448 outBuffer
.PutCharacter(format
[0]);
452 if (qualifier
== 'L')
453 num
= va_arg(args
, unsigned long long);
454 else if (qualifier
== 'l') {
455 num
= va_arg(args
, unsigned long);
456 if ((flags
& SIGN
) != 0)
458 } else if (qualifier
== 'z') {
459 num
= va_arg(args
, size_t);
460 if ((flags
& SIGN
) != 0)
462 } else if (qualifier
== 'h') {
463 num
= (unsigned short)va_arg(args
, int);
464 if ((flags
& SIGN
) != 0)
466 } else if ((flags
& SIGN
) != 0)
467 num
= va_arg(args
, int);
469 num
= va_arg(args
, unsigned int);
471 number(outBuffer
, num
, base
, fieldWidth
, precision
, flags
);
475 outBuffer
.NullTerminate();
476 return outBuffer
.BytesWritten();
481 vsprintf(char *buffer
, const char *format
, va_list args
)
483 return vsnprintf(buffer
, ~0UL, format
, args
);
488 snprintf(char *buffer
, size_t bufferSize
, const char *format
, ...)
493 va_start(args
, format
);
494 i
= vsnprintf(buffer
, bufferSize
, format
, args
);
502 sprintf(char *buffer
, const char *format
, ...)
507 va_start(args
, format
);
508 i
= vsnprintf(buffer
, ~0UL, format
, args
);