8 #define LARGEST_SIGNED long long int
10 #define LARGEST_UNSIGNED long int
14 #ifndef LARGEST_UNSIGNED
16 #define LARGEST_UNSIGNED unsigned long long int
18 #define LARGEST_UNSIGNED unsigned long int
23 #define POINTER_INT unsigned long
26 typedef unsigned int FormatFlags;
28 #define MAKE_MASK(shift,size) (((1 << size) - 1) << (shift))
30 #define JUSTIFY_SHIFT 0
31 #define JUSTIFY_SIZE 1
32 #define JUSTIFY_RIGHT 0x0000
33 #define JUSTIFY_LEFT 0x0001
34 #define JUSTIFY_MASK MAKE_MASK(JUSTIFY_SHIFT,JUSTIFY_SIZE)
38 #define POSITIVE_SHIFT (JUSTIFY_SHIFT + JUSTIFY_SIZE)
39 #define POSITIVE_NONE (0x0000 << POSITIVE_SHIFT)
40 #define POSITIVE_SPACE (0x0001 << POSITIVE_SHIFT)
41 #define POSITIVE_PLUS (0x0003 << POSITIVE_SHIFT)
42 #define POSITIVE_MASK MAKE_MASK(POSITIVE_SHIFT, POSITIVE_SIZE)
44 #define POSITIVE_SIZE 2
46 #define ALTERNATE_FORM_SHIFT (POSITIVE_SHIFT + POSITIVE_SIZE)
47 #define ALTERNATE_FORM_SIZE 1
48 #define ALTERNATE_FORM (0x0001 << ALTERNATE_FORM_SHIFT)
51 #define PAD_SHIFT (ALTERNATE_FORM_SHIFT + ALTERNATE_FORM_SIZE)
53 #define PAD_SPACE (0x0000 << PAD_SHIFT)
54 #define PAD_ZERO (0x0001 << PAD_SHIFT)
56 #define SIZE_SHIFT (PAD_SHIFT + PAD_SIZE)
58 #define SIZE_CHAR (0x0001 << SIZE_SHIFT)
59 #define SIZE_SHORT (0x0002 << SIZE_SHIFT)
60 #define SIZE_INT (0x0000 << SIZE_SHIFT)
61 #define SIZE_LONG (0x0003 << SIZE_SHIFT)
62 #define SIZE_LONGLONG (0x0004 << SIZE_SHIFT)
63 #define SIZE_MASK MAKE_MASK(SIZE_SHIFT,SIZE_SIZE)
65 #define CONV_SHIFT (SIZE_SHIFT + SIZE_SIZE)
67 #define CONV_INTEGER (0x0001 << CONV_SHIFT)
68 #define CONV_FLOAT (0x0002 << CONV_SHIFT)
69 #define CONV_POINTER (0x0003 << CONV_SHIFT)
70 #define CONV_STRING (0x0004 << CONV_SHIFT)
71 #define CONV_CHAR (0x0005 << CONV_SHIFT)
72 #define CONV_PERCENT (0x0006 << CONV_SHIFT)
73 #define CONV_WRITTEN (0x0007 << CONV_SHIFT)
74 #define CONV_MASK MAKE_MASK(CONV_SHIFT, CONV_SIZE)
76 #define RADIX_SHIFT (CONV_SHIFT + CONV_SIZE)
78 #define RADIX_DECIMAL (0x0001 << RADIX_SHIFT)
79 #define RADIX_OCTAL (0x0002 << RADIX_SHIFT)
80 #define RADIX_HEX (0x0003 << RADIX_SHIFT)
81 #define RADIX_MASK MAKE_MASK(RADIX_SHIFT,RADIX_SIZE)
83 #define SIGNED_SHIFT (RADIX_SHIFT + RADIX_SIZE)
85 #define SIGNED_NO (0x0000 << SIGNED_SHIFT)
86 #define SIGNED_YES (0x0001 << SIGNED_SHIFT)
87 #define SIGNED_MASK MAKE_MASK(SIGNED_SHIFT,SIGNED_SIZE)
89 #define CAPS_SHIFT (SIGNED_SHIFT + SIGNED_SIZE)
91 #define CAPS_NO (0x0000 << CAPS_SHIFT)
92 #define CAPS_YES (0x0001 << CAPS_SHIFT)
93 #define CAPS_MASK MAKE_MASK(CAPS_SHIFT,CAPS_SIZE)
95 #define FLOAT_SHIFT (CAPS_SHIFT + CAPS_SIZE)
97 #define FLOAT_NORMAL (0x0000 << FLOAT_SHIFT)
98 #define FLOAT_EXPONENT (0x0001 << FLOAT_SHIFT)
99 #define FLOAT_DEPENDANT (0x0002 << FLOAT_SHIFT)
100 #define FLOAT_HEX (0x0003 << FLOAT_SHIFT)
101 #define FLOAT_MASK MAKE_MASK(FLOAT_SHIFT, FLOAT_SIZE)
104 parse_flags(
const char **posp)
106 FormatFlags
flags = 0;
107 const char *pos = *posp;
111 flags |= JUSTIFY_LEFT;
114 flags |= POSITIVE_PLUS;
117 flags |= POSITIVE_SPACE;
120 flags |= ALTERNATE_FORM;
135 parse_uint(
const char **posp)
138 const char *pos = *posp;
140 while((ch = *pos) >=
'0' && ch <=
'9') {
141 v = v * 10 + (ch -
'0');
148 #define MAXCHARS_HEX ((sizeof(LARGEST_UNSIGNED) * 8) / 4 )
152 #define MAXCHARS ((sizeof(LARGEST_UNSIGNED) * 8 + 2) / 3 )
155 output_uint_decimal(
char **posp, LARGEST_UNSIGNED v)
160 *--pos = (v % 10) +
'0';
169 output_uint_hex(
char **posp, LARGEST_UNSIGNED v,
unsigned int flags)
172 const char *hex = (flags & CAPS_YES) ?
"0123456789ABCDEF":
"0123456789abcdef";
175 *--pos = hex[(v % 16)];
184 output_uint_octal(
char **posp, LARGEST_UNSIGNED v)
189 *--pos = (v % 8) +
'0';
197 static StrFormatResult
198 fill_space(
const StrFormatContext *ctxt,
unsigned int len)
201 static const char buffer[16] =
" ";
203 res = ctxt->write_str(ctxt->user_data, buffer, 16);
204 if (res != STRFORMAT_OK)
return res;
207 if (len == 0)
return STRFORMAT_OK;
208 return ctxt->write_str(ctxt->user_data, buffer, len);
211 static StrFormatResult
212 fill_zero(
const StrFormatContext *ctxt,
unsigned int len)
215 static const char buffer[16] =
"0000000000000000";
217 res = ctxt->write_str(ctxt->user_data, buffer, 16);
218 if (res != STRFORMAT_OK)
return res;
221 if (len == 0)
return STRFORMAT_OK;
222 return ctxt->write_str(ctxt->user_data, buffer, len);
225 #define CHECKCB(res) {if ((res) != STRFORMAT_OK) {va_end(ap); return -1;}}
228 format_str(
const StrFormatContext *ctxt,
const char *format, ...)
232 va_start(ap, format);
233 ret = format_str_v(ctxt, format, ap);
239 format_str_v(
const StrFormatContext *ctxt,
const char *format, va_list ap)
241 unsigned int written = 0;
242 const char *pos = format;
243 while(*pos !=
'\0') {
245 unsigned int minwidth = 0;
248 const char *start = pos;
249 while( (ch = *pos) !=
'\0' && ch !=
'%') pos++;
251 CHECKCB(ctxt->write_str(ctxt->user_data, start, pos - start));
252 written += pos - start;
263 flags = parse_flags(&pos);
266 if (*pos >=
'1' && *pos <=
'9') {
267 minwidth = parse_uint(&pos);
268 }
else if (*pos ==
'*') {
269 int w = va_arg(ap,
int);
271 flags |= JUSTIFY_LEFT;
282 if (*pos >=
'0' && *pos <=
'9') {
283 precision = parse_uint(&pos);
284 }
else if (*pos ==
'*') {
286 precision = va_arg(ap,
int);
292 flags |= SIZE_LONGLONG;
297 }
else if (*pos ==
'h') {
311 flags |= CONV_INTEGER | RADIX_DECIMAL | SIGNED_YES;
314 flags |= CONV_INTEGER | RADIX_DECIMAL | SIGNED_NO;
317 flags |= CONV_INTEGER | RADIX_OCTAL | SIGNED_NO;
320 flags |= CONV_INTEGER | RADIX_HEX | SIGNED_NO;
323 flags |= CONV_INTEGER | RADIX_HEX | SIGNED_NO | CAPS_YES;
327 flags |= CONV_FLOAT | FLOAT_NORMAL;
330 flags |= CONV_FLOAT | FLOAT_NORMAL | CAPS_YES;
333 flags |= CONV_FLOAT | FLOAT_EXPONENT;
336 flags |= CONV_FLOAT | FLOAT_EXPONENT | CAPS_YES;
339 flags |= CONV_FLOAT | FLOAT_DEPENDANT;
342 flags |= CONV_FLOAT | FLOAT_DEPENDANT | CAPS_YES;
345 flags |= CONV_FLOAT | FLOAT_HEX;
348 flags |= CONV_FLOAT | FLOAT_HEX | CAPS_YES;
355 flags |= CONV_STRING;
358 flags |= CONV_POINTER;
361 flags |= CONV_WRITTEN;
364 flags |= CONV_PERCENT;
371 switch(flags & CONV_MASK) {
373 CHECKCB(ctxt->write_str(ctxt->user_data,
"%", 1));
380 unsigned int prefix_len = 0;
381 char buffer[MAXCHARS];
382 char *conv_pos = buffer + MAXCHARS;
383 unsigned int conv_len = 0;
384 unsigned int width = 0;
385 unsigned int precision_fill;
386 unsigned int field_fill;
387 LARGEST_UNSIGNED uvalue = 0;
390 if (precision < 0) precision = 1;
391 else flags &= ~PAD_ZERO;
393 if (flags & SIGNED_YES) {
395 LARGEST_SIGNED value = 0;
396 switch(flags & SIZE_MASK) {
398 value = (
signed char)va_arg(ap,
int);
401 value = (short)va_arg(ap,
int);
404 value = va_arg(ap,
int);
406 #ifndef HAVE_LONGLONG
410 value = va_arg(ap,
long);
414 value = va_arg(ap,
long long);
426 switch(flags & SIZE_MASK) {
428 uvalue = (
unsigned char)va_arg(ap,
unsigned int);
431 uvalue = (
unsigned short)va_arg(ap,
unsigned int);
434 uvalue = va_arg(ap,
unsigned int);
436 #ifndef HAVE_LONGLONG
440 uvalue = va_arg(ap,
unsigned long);
444 uvalue = va_arg(ap,
unsigned long long);
450 switch(flags & (RADIX_MASK)) {
452 conv_len = output_uint_decimal(&conv_pos,uvalue);
455 conv_len = output_uint_octal(&conv_pos,uvalue);
458 conv_len = output_uint_hex(&conv_pos,uvalue, flags);
463 precision_fill = (precision > conv_len) ? precision - conv_len : 0;
464 if ((flags & (RADIX_MASK | ALTERNATE_FORM))
465 == (RADIX_OCTAL | ALTERNATE_FORM)) {
466 if (precision_fill < 1) precision_fill = 1;
469 width += precision_fill;
471 if ((flags & (RADIX_MASK | ALTERNATE_FORM))
472 == (RADIX_HEX | ALTERNATE_FORM) && uvalue != 0) {
474 if (flags & CAPS_YES) {
481 if (flags & SIGNED_YES) {
486 switch(flags & POSITIVE_MASK) {
501 field_fill = (minwidth > width) ? minwidth - width : 0;
503 if ((flags & JUSTIFY_MASK) == JUSTIFY_RIGHT) {
504 if (flags & PAD_ZERO) {
505 precision_fill += field_fill;
507 CHECKCB(fill_space(ctxt,field_fill));
512 CHECKCB(ctxt->write_str(ctxt->user_data, prefix, prefix_len));
513 written += prefix_len;
515 CHECKCB(fill_zero(ctxt,precision_fill));
516 written += precision_fill;
518 CHECKCB(ctxt->write_str(ctxt->user_data, conv_pos,conv_len));
521 if ((flags & JUSTIFY_MASK) == JUSTIFY_LEFT) {
522 CHECKCB(fill_space(ctxt,field_fill));
524 written += field_fill;
529 unsigned int field_fill;
531 char *str = va_arg(ap,
char *);
534 while(*pos !=
'\0') pos++;
540 if (precision >= 0 && precision < len) len = precision;
541 field_fill = (minwidth > len) ? minwidth - len : 0;
542 if ((flags & JUSTIFY_MASK) == JUSTIFY_RIGHT) {
543 CHECKCB(fill_space(ctxt,field_fill));
545 CHECKCB(ctxt->write_str(ctxt->user_data, str,len));
547 if ((flags & JUSTIFY_MASK) == JUSTIFY_LEFT) {
548 CHECKCB(fill_space(ctxt,field_fill));
550 written += field_fill;
555 LARGEST_UNSIGNED uvalue =
556 (LARGEST_UNSIGNED)(POINTER_INT)va_arg(ap,
void *);
557 char buffer[MAXCHARS_HEX + 3];
558 char *conv_pos = buffer + MAXCHARS_HEX+3;
559 unsigned int conv_len;
560 unsigned int field_fill;
562 conv_len = output_uint_hex(&conv_pos,uvalue,flags);
572 field_fill = (minwidth > conv_len) ? minwidth - conv_len : 0;
574 if ((flags & JUSTIFY_MASK) == JUSTIFY_RIGHT) {
575 CHECKCB(fill_space(ctxt,field_fill));
578 CHECKCB(ctxt->write_str(ctxt->user_data, conv_pos,conv_len));
581 if ((flags & JUSTIFY_MASK) == JUSTIFY_LEFT) {
582 CHECKCB(fill_space(ctxt,field_fill));
584 written += field_fill;
589 char ch = va_arg(ap,
int);
590 unsigned int field_fill = (minwidth > 1) ? minwidth - 1 : 0;
591 if ((flags & JUSTIFY_MASK) == JUSTIFY_RIGHT) {
592 CHECKCB(fill_space(ctxt,field_fill));
593 written += field_fill;
596 CHECKCB(ctxt->write_str(ctxt->user_data, &ch, 1));
599 if ((flags & JUSTIFY_MASK) == JUSTIFY_LEFT) {
600 CHECKCB(fill_space(ctxt,field_fill));
602 written+= field_fill;
607 int *p = va_arg(ap,
int*);