Add first structure and start work on format specifier parser
This commit is contained in:
134
src/simple-printf.c
Normal file
134
src/simple-printf.c
Normal file
@@ -0,0 +1,134 @@
|
||||
#include <simple-printf/simple-printf.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
enum format_specifier_type {
|
||||
FMT_INVALID = 0,
|
||||
FMT_INTEGER,
|
||||
FMT_UNSIGNED,
|
||||
FMT_STRING,
|
||||
FMT_HEXUINT_CAPITALIZED,
|
||||
FMT_HEXUNIT,
|
||||
FMT_CHAR,
|
||||
FMT_SIZE,
|
||||
FMT_PERCENT,
|
||||
};
|
||||
|
||||
struct format_specifier {
|
||||
enum format_specifier_type specifier;
|
||||
size_t length; /**< @brief lenght of formatted output.*/
|
||||
bool zero_pad;
|
||||
size_t length_of_provided_specifier;
|
||||
};
|
||||
|
||||
static void parse_format_specifier(const char *start, struct format_specifier *result)
|
||||
{
|
||||
size_t fmt_len = 1ull;
|
||||
bool keep_parsing = true;
|
||||
bool is_in_number = false;
|
||||
const char *number;
|
||||
size_t num_len = 0;
|
||||
|
||||
result->specifier = FMT_INVALID;
|
||||
result->zero_pad = 0;
|
||||
result->length_of_provided_specifier = 0;
|
||||
result->length = 0;
|
||||
if (!start)
|
||||
return;
|
||||
|
||||
/* Check if specifier starts with % */
|
||||
if (*start != '%')
|
||||
return;
|
||||
|
||||
start++;
|
||||
while (keep_parsing) {
|
||||
/* Parse the format specifier*/
|
||||
switch (*start) {
|
||||
case '0':
|
||||
if (fmt_len == 1) {
|
||||
result->zero_pad = 1;
|
||||
break;
|
||||
}
|
||||
/* Fallthru */
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
/* Number */
|
||||
if (!is_in_number) {
|
||||
/* Start of number */
|
||||
is_in_number = true;
|
||||
number = start;
|
||||
num_len = 0;
|
||||
} else {
|
||||
/* Continue parsing number */
|
||||
num_len++;
|
||||
}
|
||||
break;
|
||||
case 'c':
|
||||
result->specifier = FMT_CHAR;
|
||||
keep_parsing = false;
|
||||
break;
|
||||
case 'z':
|
||||
result->specifier = FMT_SIZE;
|
||||
keep_parsing = false;
|
||||
break;
|
||||
case 'x':
|
||||
result->specifier = FMT_HEXUNIT;
|
||||
keep_parsing = false;
|
||||
break;
|
||||
case 'X':
|
||||
result->specifier = FMT_HEXUINT_CAPITALIZED;
|
||||
keep_parsing = false;
|
||||
break;
|
||||
case 's':
|
||||
result->specifier = FMT_STRING;
|
||||
keep_parsing = false;
|
||||
break;
|
||||
case 'u':
|
||||
result->specifier = FMT_UNSIGNED;
|
||||
keep_parsing = false;
|
||||
break;
|
||||
case 'i': /* Falltrhu */
|
||||
case 'd':
|
||||
result->specifier = FMT_INTEGER;
|
||||
keep_parsing = false;
|
||||
break;
|
||||
case '%':
|
||||
if (fmt_len == 1) {
|
||||
result->specifier = FMT_PERCENT;
|
||||
}
|
||||
keep_parsing = false;
|
||||
default:
|
||||
/* Unrecognized stuff. Abort */
|
||||
keep_parsing = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (keep_parsing == false) {
|
||||
/* End reached. Check the number */
|
||||
|
||||
}
|
||||
|
||||
start++;
|
||||
fmt_len++;
|
||||
}
|
||||
}
|
||||
|
||||
int simple_snprintf(char *dest, size_t dest_size, const char *fmt, ...)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
if (!dest || !dest_size || !fmt) {
|
||||
/* Parameter error */
|
||||
return -1000;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
Reference in New Issue
Block a user