34 #include <strformat.h> 39 #ifndef LARGEST_SIGNED 41 #define LARGEST_SIGNED long long int 43 #define LARGEST_UNSIGNED long int 47 #ifndef LARGEST_UNSIGNED 49 #define LARGEST_UNSIGNED unsigned long long int 51 #define LARGEST_UNSIGNED unsigned long int 56 #define POINTER_INT unsigned long 59 typedef unsigned int FormatFlags;
61 #define MAKE_MASK(shift, size) (((1 << size) - 1) << (shift)) 63 #define JUSTIFY_SHIFT 0 64 #define JUSTIFY_SIZE 1 65 #define JUSTIFY_RIGHT 0x0000 66 #define JUSTIFY_LEFT 0x0001 67 #define JUSTIFY_MASK MAKE_MASK(JUSTIFY_SHIFT, JUSTIFY_SIZE) 70 #define POSITIVE_SHIFT (JUSTIFY_SHIFT + JUSTIFY_SIZE) 71 #define POSITIVE_NONE (0x0000 << POSITIVE_SHIFT) 72 #define POSITIVE_SPACE (0x0001 << POSITIVE_SHIFT) 73 #define POSITIVE_PLUS (0x0003 << POSITIVE_SHIFT) 74 #define POSITIVE_MASK MAKE_MASK(POSITIVE_SHIFT, POSITIVE_SIZE) 76 #define POSITIVE_SIZE 2 78 #define ALTERNATE_FORM_SHIFT (POSITIVE_SHIFT + POSITIVE_SIZE) 79 #define ALTERNATE_FORM_SIZE 1 80 #define ALTERNATE_FORM (0x0001 << ALTERNATE_FORM_SHIFT) 82 #define PAD_SHIFT (ALTERNATE_FORM_SHIFT + ALTERNATE_FORM_SIZE) 84 #define PAD_SPACE (0x0000 << PAD_SHIFT) 85 #define PAD_ZERO (0x0001 << PAD_SHIFT) 87 #define SIZE_SHIFT (PAD_SHIFT + PAD_SIZE) 89 #define SIZE_CHAR (0x0001 << SIZE_SHIFT) 90 #define SIZE_SHORT (0x0002 << SIZE_SHIFT) 91 #define SIZE_INT (0x0000 << SIZE_SHIFT) 92 #define SIZE_LONG (0x0003 << SIZE_SHIFT) 93 #define SIZE_LONGLONG (0x0004 << SIZE_SHIFT) 94 #define SIZE_MASK MAKE_MASK(SIZE_SHIFT, SIZE_SIZE) 96 #define CONV_SHIFT (SIZE_SHIFT + SIZE_SIZE) 98 #define CONV_INTEGER (0x0001 << CONV_SHIFT) 99 #define CONV_FLOAT (0x0002 << CONV_SHIFT) 100 #define CONV_POINTER (0x0003 << CONV_SHIFT) 101 #define CONV_STRING (0x0004 << CONV_SHIFT) 102 #define CONV_CHAR (0x0005 << CONV_SHIFT) 103 #define CONV_PERCENT (0x0006 << CONV_SHIFT) 104 #define CONV_WRITTEN (0x0007 << CONV_SHIFT) 105 #define CONV_MASK MAKE_MASK(CONV_SHIFT, CONV_SIZE) 107 #define RADIX_SHIFT (CONV_SHIFT + CONV_SIZE) 109 #define RADIX_DECIMAL (0x0001 << RADIX_SHIFT) 110 #define RADIX_OCTAL (0x0002 << RADIX_SHIFT) 111 #define RADIX_HEX (0x0003 << RADIX_SHIFT) 112 #define RADIX_MASK MAKE_MASK(RADIX_SHIFT, RADIX_SIZE) 114 #define SIGNED_SHIFT (RADIX_SHIFT + RADIX_SIZE) 115 #define SIGNED_SIZE 1 116 #define SIGNED_NO (0x0000 << SIGNED_SHIFT) 117 #define SIGNED_YES (0x0001 << SIGNED_SHIFT) 118 #define SIGNED_MASK MAKE_MASK(SIGNED_SHIFT, SIGNED_SIZE) 120 #define CAPS_SHIFT (SIGNED_SHIFT + SIGNED_SIZE) 122 #define CAPS_NO (0x0000 << CAPS_SHIFT) 123 #define CAPS_YES (0x0001 << CAPS_SHIFT) 124 #define CAPS_MASK MAKE_MASK(CAPS_SHIFT, CAPS_SIZE) 126 #define FLOAT_SHIFT (CAPS_SHIFT + CAPS_SIZE) 128 #define FLOAT_NORMAL (0x0000 << FLOAT_SHIFT) 129 #define FLOAT_EXPONENT (0x0001 << FLOAT_SHIFT) 130 #define FLOAT_DEPENDANT (0x0002 << FLOAT_SHIFT) 131 #define FLOAT_HEX (0x0003 << FLOAT_SHIFT) 132 #define FLOAT_MASK MAKE_MASK(FLOAT_SHIFT, FLOAT_SIZE) 134 #define CHECKCB(res) { if((res) != STRFORMAT_OK) { va_end(ap); return -1; } } 136 #define MAXCHARS_HEX ((sizeof(LARGEST_UNSIGNED) * 8) / 4) 139 #define MAXCHARS ((sizeof(LARGEST_UNSIGNED) * 8 + 2) / 3) 142 parse_flags(
const char **posp)
144 FormatFlags flags = 0;
145 const char *pos = *posp;
150 flags |= JUSTIFY_LEFT;
153 flags |= POSITIVE_PLUS;
156 flags |= POSITIVE_SPACE;
159 flags |= ALTERNATE_FORM;
174 parse_uint(
const char **posp)
177 const char *pos = *posp;
180 while((ch = *pos) >=
'0' && ch <=
'9') {
181 v = v * 10 + (ch -
'0');
191 output_uint_decimal(
char **posp, LARGEST_UNSIGNED v)
197 *--pos = (v % 10) +
'0';
208 output_uint_hex(
char **posp, LARGEST_UNSIGNED v,
unsigned int flags)
211 const char *hex = (flags & CAPS_YES) ?
"0123456789ABCDEF" :
"0123456789abcdef";
215 *--pos = hex[(v % 16)];
226 output_uint_octal(
char **posp, LARGEST_UNSIGNED v)
232 *--pos = (v % 8) +
'0';
242 static strformat_result
243 fill_space(
const strformat_context_t *ctxt,
unsigned int len)
245 strformat_result res;
246 static const char buffer[16] =
" ";
249 res = ctxt->write_str(ctxt->user_data, buffer, 16);
250 if(res != STRFORMAT_OK) {
260 return ctxt->write_str(ctxt->user_data, buffer, len);
263 static strformat_result
264 fill_zero(
const strformat_context_t *ctxt,
unsigned int len)
266 strformat_result res;
267 static const char buffer[16] =
"0000000000000000";
270 res = ctxt->write_str(ctxt->user_data, buffer, 16);
271 if(res != STRFORMAT_OK) {
280 return ctxt->write_str(ctxt->user_data, buffer, len);
284 format_str(
const strformat_context_t *ctxt,
const char *format, ...)
288 va_start(ap, format);
289 ret = format_str_v(ctxt, format, ap);
295 format_str_v(
const strformat_context_t *ctxt,
const char *format, va_list ap)
297 unsigned int written = 0;
298 const char *pos = format;
300 while(*pos !=
'\0') {
302 unsigned int minwidth = 0;
305 const char *
start = pos;
307 while((ch = *pos) !=
'\0' && ch !=
'%') {
312 CHECKCB(ctxt->write_str(ctxt->user_data, start, pos - start));
313 written += pos -
start;
328 flags = parse_flags(&pos);
331 if(*pos >=
'1' && *pos <=
'9') {
332 minwidth = parse_uint(&pos);
333 }
else if(*pos ==
'*') {
334 int w = va_arg(ap,
int);
337 flags |= JUSTIFY_LEFT;
350 if(*pos >=
'0' && *pos <=
'9') {
351 precision = parse_uint(&pos);
352 }
else if(*pos ==
'*') {
354 precision = va_arg(ap,
int);
362 flags |= SIZE_LONGLONG;
367 }
else if(*pos ==
'h') {
376 }
else if(*pos ==
'z') {
377 if(
sizeof(
size_t) ==
sizeof(
short)) {
379 }
else if(
sizeof(
size_t) ==
sizeof(
long)) {
382 }
else if(
sizeof(
size_t) ==
sizeof(
long long)) {
383 flags |= SIZE_LONGLONG;
393 flags |= CONV_INTEGER | RADIX_DECIMAL | SIGNED_YES;
396 flags |= CONV_INTEGER | RADIX_DECIMAL | SIGNED_NO;
399 flags |= CONV_INTEGER | RADIX_OCTAL | SIGNED_NO;
402 flags |= CONV_INTEGER | RADIX_HEX | SIGNED_NO;
405 flags |= CONV_INTEGER | RADIX_HEX | SIGNED_NO | CAPS_YES;
409 flags |= CONV_FLOAT | FLOAT_NORMAL;
412 flags |= CONV_FLOAT | FLOAT_NORMAL | CAPS_YES;
415 flags |= CONV_FLOAT | FLOAT_EXPONENT;
418 flags |= CONV_FLOAT | FLOAT_EXPONENT | CAPS_YES;
421 flags |= CONV_FLOAT | FLOAT_DEPENDANT;
424 flags |= CONV_FLOAT | FLOAT_DEPENDANT | CAPS_YES;
427 flags |= CONV_FLOAT | FLOAT_HEX;
430 flags |= CONV_FLOAT | FLOAT_HEX | CAPS_YES;
437 flags |= CONV_STRING;
440 flags |= CONV_POINTER;
443 flags |= CONV_WRITTEN;
446 flags |= CONV_PERCENT;
454 switch(flags & CONV_MASK) {
456 CHECKCB(ctxt->write_str(ctxt->user_data,
"%", 1));
463 unsigned int prefix_len = 0;
464 char buffer[MAXCHARS];
465 char *conv_pos = buffer + MAXCHARS;
466 unsigned int conv_len = 0;
467 unsigned int width = 0;
468 unsigned int precision_fill;
469 unsigned int field_fill;
470 LARGEST_UNSIGNED uvalue = 0;
479 if(flags & SIGNED_YES) {
481 LARGEST_SIGNED value = 0;
482 switch(flags & SIZE_MASK) {
484 value = (
signed char)va_arg(ap,
int);
487 value = (short)va_arg(ap,
int);
490 value = va_arg(ap,
int);
492 #ifndef HAVE_LONGLONG 496 value = va_arg(ap,
long);
500 value = va_arg(ap,
long long);
512 switch(flags & SIZE_MASK) {
514 uvalue = (
unsigned char)va_arg(ap,
unsigned int);
517 uvalue = (
unsigned short)va_arg(ap,
unsigned int);
520 uvalue = va_arg(ap,
unsigned int);
522 #ifndef HAVE_LONGLONG 526 uvalue = va_arg(ap,
unsigned long);
530 uvalue = va_arg(ap,
unsigned long long);
536 switch(flags & (RADIX_MASK)) {
538 conv_len = output_uint_decimal(&conv_pos, uvalue);
541 conv_len = output_uint_octal(&conv_pos, uvalue);
544 conv_len = output_uint_hex(&conv_pos, uvalue, flags);
549 precision_fill = (precision > conv_len) ? precision - conv_len : 0;
550 if((flags & (RADIX_MASK | ALTERNATE_FORM))
551 == (RADIX_OCTAL | ALTERNATE_FORM)) {
552 if(precision_fill < 1) {
557 width += precision_fill;
559 if((flags & (RADIX_MASK | ALTERNATE_FORM))
560 == (RADIX_HEX | ALTERNATE_FORM) && uvalue != 0) {
562 if(flags & CAPS_YES) {
569 if(flags & SIGNED_YES) {
574 switch(flags & POSITIVE_MASK) {
589 field_fill = (minwidth > width) ? minwidth - width : 0;
591 if((flags & JUSTIFY_MASK) == JUSTIFY_RIGHT) {
592 if(flags & PAD_ZERO) {
593 precision_fill += field_fill;
596 CHECKCB(fill_space(ctxt, field_fill));
601 CHECKCB(ctxt->write_str(ctxt->user_data, prefix, prefix_len));
603 written += prefix_len;
605 CHECKCB(fill_zero(ctxt, precision_fill));
606 written += precision_fill;
608 CHECKCB(ctxt->write_str(ctxt->user_data, conv_pos, conv_len));
611 if((flags & JUSTIFY_MASK) == JUSTIFY_LEFT) {
612 CHECKCB(fill_space(ctxt, field_fill));
614 written += field_fill;
619 unsigned int field_fill;
621 char *str = va_arg(ap,
char *);
625 while(*pos !=
'\0') pos++;
632 if(precision >= 0 && precision < len) {
636 field_fill = (minwidth > len) ? minwidth - len : 0;
638 if((flags & JUSTIFY_MASK) == JUSTIFY_RIGHT) {
639 CHECKCB(fill_space(ctxt, field_fill));
642 CHECKCB(ctxt->write_str(ctxt->user_data, str, len));
645 if((flags & JUSTIFY_MASK) == JUSTIFY_LEFT) {
646 CHECKCB(fill_space(ctxt, field_fill));
648 written += field_fill;
653 LARGEST_UNSIGNED uvalue =
654 (LARGEST_UNSIGNED)(POINTER_INT)va_arg(ap,
void *);
655 char buffer[MAXCHARS_HEX + 3];
656 char *conv_pos = buffer + MAXCHARS_HEX + 3;
657 unsigned int conv_len;
658 unsigned int field_fill;
660 conv_len = output_uint_hex(&conv_pos, uvalue, flags);
672 field_fill = (minwidth > conv_len) ? minwidth - conv_len : 0;
674 if((flags & JUSTIFY_MASK) == JUSTIFY_RIGHT) {
675 CHECKCB(fill_space(ctxt, field_fill));
678 CHECKCB(ctxt->write_str(ctxt->user_data, conv_pos, conv_len));
681 if((flags & JUSTIFY_MASK) == JUSTIFY_LEFT) {
682 CHECKCB(fill_space(ctxt, field_fill));
685 written += field_fill;
690 char ch = va_arg(ap,
int);
691 unsigned int field_fill = (minwidth > 1) ? minwidth - 1 : 0;
693 if((flags & JUSTIFY_MASK) == JUSTIFY_RIGHT) {
694 CHECKCB(fill_space(ctxt, field_fill));
695 written += field_fill;
698 CHECKCB(ctxt->write_str(ctxt->user_data, &ch, 1));
701 if((flags & JUSTIFY_MASK) == JUSTIFY_LEFT) {
702 CHECKCB(fill_space(ctxt, field_fill));
704 written += field_fill;
709 int *p = va_arg(ap,
int *);
static void start(void)
Start measurement.