Skip to content

Commit

Permalink
Add K and k fields, add description of B/b and K/k
Browse files Browse the repository at this point in the history
  • Loading branch information
MaJerle committed Aug 21, 2020
1 parent 83771d8 commit d0037d3
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 18 deletions.
20 changes: 14 additions & 6 deletions dev/VisualStudio/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,14 @@ main(void) {
printf("%lf\r\n", num);
printf("%lf\r\n", num - (double)((long)(num)));

printf_run("% 3u", 28);
printf_run("% 3u", 123456);
printf_run("%03u", 28);
printf_run("%03u", 123456);
printf_run("%-010uabc", 123456);
printf_run("%010uabc", 123456);
printf_run("% 3u", (unsigned)28);
printf_run("% 3u", (unsigned)123456);
printf_run("%03u", (unsigned)28);
printf_run("%+03u", (unsigned)28);
printf_run("%+3u", (unsigned)28);
printf_run("%03u", (unsigned)123456);
printf_run("%-010uabc", (unsigned)123456);
printf_run("%010uabc", (unsigned)123456);
printf_run("%-10d", -123);
printf_run("%10d", -123);
printf_run("%-06d", -1234567);
Expand Down Expand Up @@ -122,6 +124,12 @@ main(void) {
printf_run("%.3f", 12.1337);
printf_run("%.25f", 12.1337);

/* Array test */
uint8_t my_arr[] = { 0x00, 0x01, 0x02, 0x03, 0x04 };
printf_run("%5K", my_arr); /* Print fixed length */
printf_run("%*K", 3, my_arr); /* Print only first 3 elements of array */
printf_run("% *K", 3, my_arr); /* Print only first 3 elements of array with spaces between bytes */

/* Print final output */
printf("----\r\n\r\n");
printf("Number of tests passed: %d\r\n", (int)tests_passed);
Expand Down
22 changes: 22 additions & 0 deletions docs/user-manual/format-specifier.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,28 @@
Format specifier
================

Syntax
******

Full syntax for format specifier is
``%[parameter][flags][width][.precision][length]type``

Additional specifiers
*********************

LwPRINTF implementation supports some modifiers that are usually not available in standard implementation.
Those are more targeting embedded systems although they may be used in any general-purpose application

+-------------+--------------------------------------------------------------------------+
| Specifier | Description |
+=============+==========================================================================+
| ``B`` ``b`` | Prints ``unsigned int`` data as binary representation. |
+-------------+--------------------------------------------------------------------------+
| ``K`` ``k`` | Prints ``unsigned char`` based data array as sequence of hex numbers. |
| | Use *width* field to specify length of input array. |
| | Use ``K`` for uppercase hex letters, ``k`` for small. |
+-------------+--------------------------------------------------------------------------+

.. toctree::
:maxdepth: 2

59 changes: 47 additions & 12 deletions lwprintf/src/lwprintf/lwprintf.c
Original file line number Diff line number Diff line change
Expand Up @@ -248,9 +248,13 @@ prv_out_str_before(lwprintf_int_t* p, size_t buff_size) {
}
}

/* Add negative sign before when zeros are used to fill width */
if (p->m.flags.is_negative && p->m.flags.zero) {
p->out_fn(p, '-');
/* Add negative sign (or positive in case of + flag) before when zeros are used to fill width */
if (p->m.flags.zero) {
if (p->m.flags.is_negative) {
p->out_fn(p, '-');
} else if (p->m.flags.plus) {
p->out_fn(p, '+');
}
}

/* Check for flags output */
Expand All @@ -271,8 +275,12 @@ prv_out_str_before(lwprintf_int_t* p, size_t buff_size) {
}

/* Add negative sign here when spaces are used for width */
if (p->m.flags.is_negative && !p->m.flags.zero) {
p->out_fn(p, '-');
if (!p->m.flags.zero) {
if (p->m.flags.is_negative) {
p->out_fn(p, '-');
} else if (p->m.flags.plus) {
p->out_fn(p, '+');
}
}

return 1;
Expand Down Expand Up @@ -633,16 +641,16 @@ prv_format(lwprintf_int_t* p, va_list arg) {
p->m.flags.zero = 1; /* Zero padding */
p->m.width = sizeof(void*) * 2; /* Number is in hex format and byte is represented with 2 letters */

if (0) {
#if LWPRINTF_CFG_SUPPORT_LONG_LONG
if (sizeof(void*) == sizeof(unsigned long long int)) {
} else if (sizeof(void*) == sizeof(unsigned long long int)) {
prv_unsigned_longlong_int_to_str(p, (unsigned long long int)((uintptr_t)va_arg(arg, void*)));
} else
#endif /* LWPRINTF_CFG_SUPPORT_LONG_LONG */
if (sizeof(void*) == sizeof(unsigned long int)) {
prv_unsigned_long_int_to_str(p, (unsigned long int)((uintptr_t)va_arg(arg, void*)));
} else {
prv_unsigned_int_to_str(p, (unsigned int)((uintptr_t)va_arg(arg, void*)));
}
} else if (sizeof(void*) == sizeof(unsigned long int)) {
prv_unsigned_long_int_to_str(p, (unsigned long int)((uintptr_t)va_arg(arg, void*)));
} else {
prv_unsigned_int_to_str(p, (unsigned int)((uintptr_t)va_arg(arg, void*)));
}
break;
}
#endif /* LWPRINTF_CFG_SUPPORT_TYPE_POINTER */
Expand All @@ -660,6 +668,33 @@ prv_format(lwprintf_int_t* p, va_list arg) {
case '%':
p->out_fn(p, '%');
break;
/*
* This is to print unsigned-char formatted pointer in hex string
*
* char arr[] = {0, 1, 2, 3, 255};
* "%5K" would produce 00010203FF
*/
case 'k':
case 'K': {
unsigned char* ptr = (void *)va_arg(arg, unsigned char *); /* Get input parameter as unsigned char pointer */
int len = p->m.width;

p->m.flags.uc = *fmt == 'K'; /* Set if uppercase */
p->m.flags.precision = 1; /* We use precision flag */
p->m.precision = 2; /* 2 bytes output, 0 prepend if necessary */
p->m.flags.zero = 1; /* Prepend with zeros */
p->m.width = 2; /* Each number is 2 chars min/max */
p->m.base = 16; /* Hex format */

/* Output byte by byte w/o hex prefix */
for (int i = 0; i < len; ++i) {
prv_unsigned_int_to_str(p, (unsigned int)*ptr++);
if (p->m.flags.space && i < (len - 1)) {
p->out_fn(p, ' '); /* Generate space between numbers */
}
}
break;
}
default:
p->out_fn(p, *fmt);
}
Expand Down

0 comments on commit d0037d3

Please sign in to comment.