programmable field width (e.g. %*c)
This commit is contained in:
parent
9048955245
commit
c1512cde98
42
embformat.c
42
embformat.c
@ -28,6 +28,7 @@ typedef enum {
|
||||
} FmtType;
|
||||
|
||||
struct _FmtWord;
|
||||
|
||||
typedef int (*printfn)(va_list *va, struct _FmtWord *fmt, char *outbuf, size_t free_space);
|
||||
|
||||
// pair of type and designator character
|
||||
@ -336,11 +337,13 @@ static int pfn_double(va_list *va, FmtWord *fmt, char *outbuf, size_t free_space
|
||||
// print character
|
||||
static int pfn_char(va_list *va, FmtWord *fmt, char *outbuf, size_t free_space) {
|
||||
int c = va_arg((*va), int);
|
||||
if (free_space >= 1) {
|
||||
outbuf[0] = (char) c;
|
||||
outbuf[1] = '\0';
|
||||
unsigned rep = (fmt->width == 0) ? 1 : fmt->width; // determine repetition count
|
||||
rep = MIN(free_space, rep);
|
||||
for (unsigned i = 0; i < rep; i++) {
|
||||
outbuf[i] = (char)c;
|
||||
}
|
||||
return 1;
|
||||
outbuf[rep] = '\0';
|
||||
return rep;
|
||||
}
|
||||
|
||||
// print string
|
||||
@ -350,9 +353,18 @@ static int pfn_string(va_list *va, FmtWord *fmt, char *outbuf, size_t free_space
|
||||
}
|
||||
|
||||
// format swting assignment table
|
||||
static FmtTypeDesignatorPair sTypeDesAssignment[] = { { '%', LITERAL_PERCENT, pfn_literal_percent }, { 'd', SIGNED_INTEGER, pfn_integer }, { 'i', SIGNED_INTEGER, pfn_integer }, { 'u',
|
||||
UNSIGNED_INTEGER, pfn_integer }, { 'f', DOUBLE, pfn_double }, { 'e', DOUBLE_EXPONENTIAL, pfn_double }, { 'x', UNSIGNED_HEXADECIMAL_INT, pfn_integer }, { 'X',
|
||||
UNSIGNED_HEXADECIMAL_INT_UPPERCASE, pfn_integer }, { 'p', UNSIGNED_HEXADECIMAL_INT, pfn_integer }, { 's', STRING, pfn_string }, { 'c', CHARACTER, pfn_char }, { '\0', UNKNOWN } // termination
|
||||
static FmtTypeDesignatorPair sTypeDesAssignment[] = {{'%', LITERAL_PERCENT, pfn_literal_percent},
|
||||
{'d', SIGNED_INTEGER, pfn_integer},
|
||||
{'i', SIGNED_INTEGER, pfn_integer},
|
||||
{'u', UNSIGNED_INTEGER, pfn_integer},
|
||||
{'f', DOUBLE, pfn_double},
|
||||
{'e', DOUBLE_EXPONENTIAL, pfn_double},
|
||||
{'x', UNSIGNED_HEXADECIMAL_INT, pfn_integer},
|
||||
{'X', UNSIGNED_HEXADECIMAL_INT_UPPERCASE, pfn_integer},
|
||||
{'p', UNSIGNED_HEXADECIMAL_INT, pfn_integer},
|
||||
{'s', STRING, pfn_string},
|
||||
{'c', CHARACTER, pfn_char},
|
||||
{'\0', UNKNOWN} // termination
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------
|
||||
@ -468,6 +480,7 @@ static FmtTypeDesignatorPair* get_type_by_designator(char designator) {
|
||||
}
|
||||
|
||||
#define DEFAULT_PRINT_PRECISION (6)
|
||||
#define LENGTH_IS_PARAMETER (-2) // -1 is used for something else
|
||||
|
||||
static char sFlags[] = " 0+";
|
||||
|
||||
@ -507,7 +520,12 @@ static int process_format_word(char *str, FmtWord *word, int *rewind) {
|
||||
}
|
||||
|
||||
// 2.: look for width
|
||||
if (*str == '*') { // parametered width
|
||||
str++;
|
||||
word->width = LENGTH_IS_PARAMETER; // read length from the varargs
|
||||
} else {
|
||||
str = fetch_number(str, &(word->width));
|
||||
}
|
||||
|
||||
// 3.: look for precision
|
||||
word->precision = DEFAULT_PRINT_PRECISION; // default double precision
|
||||
@ -555,11 +573,19 @@ unsigned long int vembfmt(char *str, unsigned long int len, char *format, va_lis
|
||||
sum_copy_len += copy_len;
|
||||
|
||||
// print data
|
||||
FmtWord word;
|
||||
FmtWord word = { 0 };
|
||||
int rewind;
|
||||
process_format_word(word_str, &word, &rewind);
|
||||
if (word.type != UNKNOWN) {
|
||||
if (word.width == LENGTH_IS_PARAMETER) { // if length is passed in parameter...
|
||||
word.width = va_arg(args, unsigned); // read length parameter
|
||||
}
|
||||
|
||||
#ifdef COMPILE_FOR_LINUX
|
||||
int copy_len = word.pTypeDes->fn(args, &word, str, free_space); // variable with the same name!
|
||||
#else
|
||||
int copy_len = word.pTypeDes->fn(&args, &word, str, free_space); // variable with the same name!
|
||||
#endif
|
||||
free_space -= copy_len;
|
||||
str += copy_len;
|
||||
sum_copy_len += copy_len;
|
||||
|
Loading…
x
Reference in New Issue
Block a user