diff --git a/Makefile.am b/Makefile.am index 8b1e799..3729b68 100644 --- a/Makefile.am +++ b/Makefile.am @@ -63,6 +63,9 @@ endif if WITH_ELF libkernaux_a_SOURCES += src/elf.c endif +if WITH_FILE +libkernaux_a_SOURCES += src/file.c +endif if WITH_FRAMEBUFFER libkernaux_a_SOURCES += src/framebuffer.c endif @@ -130,29 +133,33 @@ examples_cmdline_SOURCES = examples/cmdline.c endif endif -################### +#################### # examples/fprintf # -################### +#################### if ENABLE_TESTS if WITH_PRINTF +if WITH_FILE TESTS += examples/fprintf examples_fprintf_LDADD = libkernaux.a examples_fprintf_SOURCES = examples/fprintf.c endif endif +endif -###################### +####################### # examples/fprintf_va # -###################### +####################### if ENABLE_TESTS if WITH_PRINTF +if WITH_FILE TESTS += examples/fprintf_va examples_fprintf_va_LDADD = libkernaux.a examples_fprintf_va_SOURCES = examples/fprintf_va.c endif endif +endif ################# # examples/ntoa # diff --git a/examples/fprintf.c b/examples/fprintf.c index b101a47..79acf62 100644 --- a/examples/fprintf.c +++ b/examples/fprintf.c @@ -1,3 +1,4 @@ +#include #include #include @@ -21,8 +22,9 @@ static void my_putchar(const char chr, void *arg) int main() { + struct KernAux_File file = KernAux_File_create(my_putchar); const int result = kernaux_fprintf( - my_putchar, + &file, (char*)data, "Hello, %s! Session ID: %u.", "Alex", diff --git a/examples/fprintf_va.c b/examples/fprintf_va.c index 25adf8a..bc53772 100644 --- a/examples/fprintf_va.c +++ b/examples/fprintf_va.c @@ -1,3 +1,4 @@ +#include #include #include @@ -23,7 +24,8 @@ static int my_printf(const char *const format, ...) { va_list va; va_start(va, format); - const int result = kernaux_vfprintf(my_putchar, (char*)data, format, va); + struct KernAux_File file = KernAux_File_create(my_putchar); + const int result = kernaux_vfprintf(&file, (char*)data, format, va); va_end(va); return result; } diff --git a/include/kernaux/file.h b/include/kernaux/file.h index dbcc5d9..0af4c30 100644 --- a/include/kernaux/file.h +++ b/include/kernaux/file.h @@ -7,6 +7,13 @@ extern "C" { typedef void (*KernAux_File_Out)(char c, void *arg); +typedef struct KernAux_File { + KernAux_File_Out out; +} *KernAux_File; + +struct KernAux_File KernAux_File_create(KernAux_File_Out out); +void KernAux_File_init(KernAux_File file, KernAux_File_Out out); + #ifdef __cplusplus } #endif diff --git a/include/kernaux/printf.h.in b/include/kernaux/printf.h.in index 425e908..8e26dbb 100644 --- a/include/kernaux/printf.h.in +++ b/include/kernaux/printf.h.in @@ -12,14 +12,14 @@ extern "C" { /** * Tiny [v]fprintf implementation - * \param out An output function which takes one character and an argument pointer + * \param file An output file * \param arg An argument pointer for user data passed to output function * \param format A string that specifies the format of the output * \param va A value identifying a variable arguments list * \return The number of characters that are sent to the output function, not counting the terminating null character */ -@comment_line_file@int kernaux_fprintf(KernAux_File_Out out, void* arg, const char* format, ...); -@comment_line_file@int kernaux_vfprintf(KernAux_File_Out out, void* arg, const char* format, va_list va); +@comment_line_file@int kernaux_fprintf(KernAux_File file, void* arg, const char* format, ...); +@comment_line_file@int kernaux_vfprintf(KernAux_File file, void* arg, const char* format, va_list va); /** * Tiny [v]snprintf implementation diff --git a/src/console.c b/src/console.c index 412d454..53b4dfb 100644 --- a/src/console.c +++ b/src/console.c @@ -13,13 +13,17 @@ #ifdef ASM_X86_64 #include #endif + +#ifdef WITH_FILE +#include +#endif #ifdef WITH_PRINTF #include #endif #include -#ifdef WITH_PRINTF +#if defined(WITH_FILE) && defined(WITH_PRINTF) static void kernaux_console_printf_putc( const char c, void *const arg __attribute__((unused)) @@ -47,14 +51,15 @@ void kernaux_console_print(const char *const s) } } -#ifdef WITH_PRINTF +#if defined(WITH_FILE) && defined(WITH_PRINTF) void kernaux_console_printf(const char *format, ...) { KERNAUX_NOTNULL_RETURN(format); va_list va; va_start(va, format); - kernaux_vfprintf(kernaux_console_printf_putc, NULL, format, va); + struct KernAux_File file = KernAux_File_create(kernaux_console_printf_putc); + kernaux_vfprintf(&file, NULL, format, va); va_end(va); } #endif diff --git a/src/file.c b/src/file.c new file mode 100644 index 0000000..b20305f --- /dev/null +++ b/src/file.c @@ -0,0 +1,23 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include + +struct KernAux_File KernAux_File_create(const KernAux_File_Out out) +{ + struct KernAux_File file; + KernAux_File_init(&file, out); + return file; +} + +void KernAux_File_init(const KernAux_File file, const KernAux_File_Out out) +{ + KERNAUX_NOTNULL_RETURN(file); + KERNAUX_NOTNULL_RETURN(out); + + file->out = out; +} diff --git a/src/printf.c b/src/printf.c index 408af28..69356b8 100644 --- a/src/printf.c +++ b/src/printf.c @@ -66,28 +66,32 @@ static size_t _etoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, d * Implementations: main API * *****************************/ -int kernaux_fprintf(void (*out)(char character, void* arg), void* arg, const char* format, ...) +#ifdef WITH_FILE + +int kernaux_fprintf(const KernAux_File file, void* arg, const char* format, ...) { - KERNAUX_NOTNULL_RETVAL(out, 0); + KERNAUX_NOTNULL_RETVAL(file, 0); KERNAUX_NOTNULL_RETVAL(format, 0); va_list va; va_start(va, format); - const out_fct_wrap_type out_fct_wrap = { out, arg }; + const out_fct_wrap_type out_fct_wrap = { file->out, arg }; const int ret = _vsnprintf(_out_fct, (char*)(uintptr_t)&out_fct_wrap, (size_t)-1, format, va); va_end(va); return ret; } -int kernaux_vfprintf(void (*out)(char character, void* arg), void* arg, const char* format, va_list va) +int kernaux_vfprintf(const KernAux_File file, void* arg, const char* format, va_list va) { - KERNAUX_NOTNULL_RETVAL(out, 0); + KERNAUX_NOTNULL_RETVAL(file, 0); KERNAUX_NOTNULL_RETVAL(format, 0); - const out_fct_wrap_type out_fct_wrap = { out, arg }; + const out_fct_wrap_type out_fct_wrap = { file->out, arg }; return _vsnprintf(_out_fct, (char*)(uintptr_t)&out_fct_wrap, (size_t)-1, format, va); } +#endif // WITH_FILE + int kernaux_snprintf(char* buffer, size_t count, const char* format, ...) { KERNAUX_NOTNULL_RETVAL(buffer, 0); diff --git a/tests/printf_gen.jinja b/tests/printf_gen.jinja index cd530a0..d579de5 100644 --- a/tests/printf_gen.jinja +++ b/tests/printf_gen.jinja @@ -4,6 +4,10 @@ #include +#ifdef WITH_FILE +#include +#endif + #include #include #include @@ -11,11 +15,13 @@ #define BUFFER_SIZE 1024 -static const char *const data = "foobar"; - static char buffer[BUFFER_SIZE]; static size_t buffer_index; +#ifdef WITH_FILE + +static const char *const data = "foobar"; + static void test_putchar(const char chr, void *const arg) { assert(arg == data); @@ -28,18 +34,23 @@ static void test_putchar(const char chr, void *const arg) buffer[buffer_index++] = chr; } +#endif // WITH_FILE + static void test(const char *const expected, const char *const format, ...) { va_list va; int result; +#ifdef WITH_FILE memset(buffer, '\0', sizeof(buffer)); buffer_index = 0; va_start(va, format); - result = kernaux_vfprintf(test_putchar, (char*)data, format, va); + struct KernAux_File file = KernAux_File_create(test_putchar); + result = kernaux_vfprintf(&file, (char*)data, format, va); va_end(va); assert((size_t)result == strlen(expected)); assert(strcmp(expected, buffer) == 0); +#endif memset(buffer, '\0', sizeof(buffer)); buffer_index = 0; @@ -52,10 +63,13 @@ static void test(const char *const expected, const char *const format, ...) int main() { +#ifdef WITH_FILE memset(buffer, '\0', sizeof(buffer)); buffer_index = 0; - kernaux_fprintf(test_putchar, (char*)data, "Hello, World!"); + struct KernAux_File file = KernAux_File_create(test_putchar); + kernaux_fprintf(&file, (char*)data, "Hello, World!"); assert(strcmp("Hello, World!", buffer) == 0); +#endif {% for case in cases %} {% if case.float %}