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') {
382 flags |= CONV_INTEGER | RADIX_DECIMAL | SIGNED_YES;
385 flags |= CONV_INTEGER | RADIX_DECIMAL | SIGNED_NO;
388 flags |= CONV_INTEGER | RADIX_OCTAL | SIGNED_NO;
391 flags |= CONV_INTEGER | RADIX_HEX | SIGNED_NO;
394 flags |= CONV_INTEGER | RADIX_HEX | SIGNED_NO | CAPS_YES;
398 flags |= CONV_FLOAT | FLOAT_NORMAL;
401 flags |= CONV_FLOAT | FLOAT_NORMAL | CAPS_YES;
404 flags |= CONV_FLOAT | FLOAT_EXPONENT;
407 flags |= CONV_FLOAT | FLOAT_EXPONENT | CAPS_YES;
410 flags |= CONV_FLOAT | FLOAT_DEPENDANT;
413 flags |= CONV_FLOAT | FLOAT_DEPENDANT | CAPS_YES;
416 flags |= CONV_FLOAT | FLOAT_HEX;
419 flags |= CONV_FLOAT | FLOAT_HEX | CAPS_YES;
426 flags |= CONV_STRING;
429 flags |= CONV_POINTER;
432 flags |= CONV_WRITTEN;
435 flags |= CONV_PERCENT;
443 switch(flags & CONV_MASK) {
445 CHECKCB(ctxt->write_str(ctxt->user_data,
"%", 1));
452 unsigned int prefix_len = 0;
453 char buffer[MAXCHARS];
454 char *conv_pos = buffer + MAXCHARS;
455 unsigned int conv_len = 0;
456 unsigned int width = 0;
457 unsigned int precision_fill;
458 unsigned int field_fill;
459 LARGEST_UNSIGNED uvalue = 0;
468 if(flags & SIGNED_YES) {
470 LARGEST_SIGNED value = 0;
471 switch(flags & SIZE_MASK) {
473 value = (
signed char)va_arg(ap,
int);
476 value = (short)va_arg(ap,
int);
479 value = va_arg(ap,
int);
481 #ifndef HAVE_LONGLONG 485 value = va_arg(ap,
long);
489 value = va_arg(ap,
long long);
501 switch(flags & SIZE_MASK) {
503 uvalue = (
unsigned char)va_arg(ap,
unsigned int);
506 uvalue = (
unsigned short)va_arg(ap,
unsigned int);
509 uvalue = va_arg(ap,
unsigned int);
511 #ifndef HAVE_LONGLONG 515 uvalue = va_arg(ap,
unsigned long);
519 uvalue = va_arg(ap,
unsigned long long);
525 switch(flags & (RADIX_MASK)) {
527 conv_len = output_uint_decimal(&conv_pos, uvalue);
530 conv_len = output_uint_octal(&conv_pos, uvalue);
533 conv_len = output_uint_hex(&conv_pos, uvalue, flags);
538 precision_fill = (precision > conv_len) ? precision - conv_len : 0;
539 if((flags & (RADIX_MASK | ALTERNATE_FORM))
540 == (RADIX_OCTAL | ALTERNATE_FORM)) {
541 if(precision_fill < 1) {
546 width += precision_fill;
548 if((flags & (RADIX_MASK | ALTERNATE_FORM))
549 == (RADIX_HEX | ALTERNATE_FORM) && uvalue != 0) {
551 if(flags & CAPS_YES) {
558 if(flags & SIGNED_YES) {
563 switch(flags & POSITIVE_MASK) {
578 field_fill = (minwidth > width) ? minwidth - width : 0;
580 if((flags & JUSTIFY_MASK) == JUSTIFY_RIGHT) {
581 if(flags & PAD_ZERO) {
582 precision_fill += field_fill;
585 CHECKCB(fill_space(ctxt, field_fill));
590 CHECKCB(ctxt->write_str(ctxt->user_data, prefix, prefix_len));
592 written += prefix_len;
594 CHECKCB(fill_zero(ctxt, precision_fill));
595 written += precision_fill;
597 CHECKCB(ctxt->write_str(ctxt->user_data, conv_pos, conv_len));
600 if((flags & JUSTIFY_MASK) == JUSTIFY_LEFT) {
601 CHECKCB(fill_space(ctxt, field_fill));
603 written += field_fill;
608 unsigned int field_fill;
610 char *str = va_arg(ap,
char *);
614 while(*pos !=
'\0') pos++;
621 if(precision >= 0 && precision < len) {
625 field_fill = (minwidth > len) ? minwidth - len : 0;
627 if((flags & JUSTIFY_MASK) == JUSTIFY_RIGHT) {
628 CHECKCB(fill_space(ctxt, field_fill));
631 CHECKCB(ctxt->write_str(ctxt->user_data, str, len));
634 if((flags & JUSTIFY_MASK) == JUSTIFY_LEFT) {
635 CHECKCB(fill_space(ctxt, field_fill));
637 written += field_fill;
642 LARGEST_UNSIGNED uvalue =
643 (LARGEST_UNSIGNED)(POINTER_INT)va_arg(ap,
void *);
644 char buffer[MAXCHARS_HEX + 3];
645 char *conv_pos = buffer + MAXCHARS_HEX + 3;
646 unsigned int conv_len;
647 unsigned int field_fill;
649 conv_len = output_uint_hex(&conv_pos, uvalue, flags);
661 field_fill = (minwidth > conv_len) ? minwidth - conv_len : 0;
663 if((flags & JUSTIFY_MASK) == JUSTIFY_RIGHT) {
664 CHECKCB(fill_space(ctxt, field_fill));
667 CHECKCB(ctxt->write_str(ctxt->user_data, conv_pos, conv_len));
670 if((flags & JUSTIFY_MASK) == JUSTIFY_LEFT) {
671 CHECKCB(fill_space(ctxt, field_fill));
674 written += field_fill;
679 char ch = va_arg(ap,
int);
680 unsigned int field_fill = (minwidth > 1) ? minwidth - 1 : 0;
682 if((flags & JUSTIFY_MASK) == JUSTIFY_RIGHT) {
683 CHECKCB(fill_space(ctxt, field_fill));
684 written += field_fill;
687 CHECKCB(ctxt->write_str(ctxt->user_data, &ch, 1));
690 if((flags & JUSTIFY_MASK) == JUSTIFY_LEFT) {
691 CHECKCB(fill_space(ctxt, field_fill));
693 written += field_fill;
698 int *p = va_arg(ap,
int *);
static void start(void)
Start measurement.