mirror of
https://github.com/tailix/libkernaux.git
synced 2024-12-04 11:25:18 -05:00
Remove generic file API (#108)
This commit is contained in:
parent
123bddd19c
commit
15ed72fee5
19 changed files with 38 additions and 380 deletions
|
@ -2,7 +2,7 @@
|
|||
# For GNU/Linux CI see GitHub Actions.
|
||||
|
||||
freebsd_instance:
|
||||
image_family: freebsd-13-0
|
||||
image_family: freebsd-13-1
|
||||
|
||||
main_freebsd_task:
|
||||
name: Main (FreeBSD)
|
||||
|
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -107,7 +107,6 @@
|
|||
|
||||
/examples/assert
|
||||
/examples/cmdline
|
||||
/examples/generic_file
|
||||
/examples/generic_malloc
|
||||
/examples/generic_mutex
|
||||
/examples/macro_bits
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
2022-11-26 Alex Kotov <kotovalexarian@gmail.com>
|
||||
|
||||
* include/kernaux/printf.h: Change API
|
||||
|
||||
2022-06-30 Alex Kotov <kotovalexarian@gmail.com>
|
||||
|
||||
* include/kernaux/macro.h: Added macros "KERNAUX_BITS[8|16|32|64]"
|
||||
|
@ -9,9 +13,7 @@
|
|||
2022-06-25 Alex Kotov <kotovalexarian@gmail.com>
|
||||
|
||||
* configure.ac: Removed package "io"
|
||||
* include/kernaux/generic/file.h: Added
|
||||
* include/kernaux/io.h: Removed
|
||||
* include/kernaux/printf.h: Use new file API
|
||||
|
||||
2022-06-24 Alex Kotov <kotovalexarian@gmail.com>
|
||||
|
||||
|
|
|
@ -31,7 +31,6 @@ libkernaux_la_LIBADD =
|
|||
libkernaux_la_SOURCES = \
|
||||
src/assert.c \
|
||||
src/libc.h \
|
||||
src/generic/file.c \
|
||||
src/generic/malloc.c \
|
||||
src/generic/mutex.c
|
||||
|
||||
|
|
|
@ -48,8 +48,6 @@ zero). Work-in-progress APIs can change at any time.
|
|||
* [Example: Panic](/examples/panic.c)
|
||||
* Stack trace *(planned)*
|
||||
* Generic types
|
||||
* [File](/include/kernaux/generic/file.h) (*non-breaking since* **?.?.?**)
|
||||
* [Example](/examples/generic_file.c)
|
||||
* [Memory allocator](/include/kernaux/generic/malloc.h) (*non-breaking since* **?.?.?**)
|
||||
* [Example](/examples/generic_malloc.c)
|
||||
* [Mutex](/include/kernaux/generic/mutex.h) (*non-breaking since* **?.?.?**)
|
||||
|
|
|
@ -63,6 +63,8 @@ if KernAux::Version.with_printf?
|
|||
else
|
||||
raise "Unknown format: #{args.inspect}"
|
||||
end
|
||||
elsif item.is_a?(Float) && item.round == item
|
||||
item.round
|
||||
else
|
||||
item
|
||||
end
|
||||
|
|
|
@ -21,14 +21,6 @@ cmdline_LDADD = $(top_builddir)/libkernaux.la
|
|||
cmdline_SOURCES = main.c cmdline.c
|
||||
endif
|
||||
|
||||
################
|
||||
# generic_file #
|
||||
################
|
||||
|
||||
TESTS += generic_file
|
||||
generic_file_LDADD = $(top_builddir)/libkernaux.la
|
||||
generic_file_SOURCES = main.c generic_file.c
|
||||
|
||||
##################
|
||||
# generic_malloc #
|
||||
##################
|
||||
|
|
|
@ -1,134 +0,0 @@
|
|||
//===========
|
||||
// my_file.c
|
||||
//===========
|
||||
|
||||
// To not always use macro "KERNAUX_PROTECTED_FIELD" around the names of
|
||||
// structure fields you may define "KERNAUX_ACCESS_PROTECTED" before including
|
||||
// any other headers, but ONLY in the file where you implement a generic type.
|
||||
//
|
||||
#define KERNAUX_ACCESS_PROTECTED
|
||||
|
||||
//===========
|
||||
// my_file.h
|
||||
//===========
|
||||
|
||||
#include <kernaux/generic/file.h>
|
||||
#include <stddef.h>
|
||||
|
||||
typedef struct MyFile {
|
||||
struct KernAux_File file;
|
||||
char *ptr;
|
||||
size_t size;
|
||||
size_t pos;
|
||||
} *MyFile;
|
||||
|
||||
struct MyFile MyFile_create(char *ptr, size_t size);
|
||||
|
||||
//===========
|
||||
// my_file.c
|
||||
//===========
|
||||
|
||||
#include <kernaux/generic/file.h>
|
||||
#include <kernaux/macro.h>
|
||||
#include <stddef.h>
|
||||
|
||||
static int MyFile_getc (void *file);
|
||||
static int MyFile_putc (void *file, unsigned char c);
|
||||
static void MyFile_rewind(void *file);
|
||||
|
||||
struct MyFile MyFile_create(char *const ptr, const size_t size)
|
||||
{
|
||||
struct MyFile my_file;
|
||||
my_file.file.getc = MyFile_getc;
|
||||
my_file.file.putc = MyFile_putc;
|
||||
my_file.file.gets = NULL; // "gets" has a default implementation
|
||||
my_file.file.puts = NULL; // "puts" has a default implementation
|
||||
my_file.file.read = NULL; // "read" has a default implementation
|
||||
my_file.file.write = NULL; // "write" has a default implementation
|
||||
my_file.file.rewind = MyFile_rewind;
|
||||
my_file.ptr = ptr;
|
||||
my_file.size = size;
|
||||
my_file.pos = 0;
|
||||
return my_file;
|
||||
}
|
||||
|
||||
int MyFile_getc(void *const file)
|
||||
{
|
||||
const MyFile my_file = file;
|
||||
if (my_file->pos >= my_file->size) return KERNAUX_EOF;
|
||||
const unsigned char c = my_file->ptr[my_file->pos++];
|
||||
return c;
|
||||
}
|
||||
|
||||
int MyFile_putc(void *const file, const unsigned char c)
|
||||
{
|
||||
const MyFile my_file = file;
|
||||
if (my_file->pos >= my_file->size) return KERNAUX_EOF;
|
||||
my_file->ptr[my_file->pos++] = c;
|
||||
return c;
|
||||
}
|
||||
|
||||
void MyFile_rewind(void *const file)
|
||||
{
|
||||
const MyFile my_file = file;
|
||||
my_file->pos = 0;
|
||||
}
|
||||
|
||||
//========
|
||||
// main.c
|
||||
//========
|
||||
|
||||
#include <kernaux/macro.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
static const char *const hello = "Hello, World!";
|
||||
|
||||
void example_main()
|
||||
{
|
||||
char buffer[20];
|
||||
char tmp_buffer[20];
|
||||
size_t count;
|
||||
|
||||
char data[6];
|
||||
memset(&data[0], 0xf0, 3);
|
||||
memset(&data[3], 0xff, 3);
|
||||
|
||||
|
||||
// Create file
|
||||
struct MyFile my_file = MyFile_create(buffer, sizeof(buffer));
|
||||
|
||||
// Write "Hello, World!" to the file
|
||||
assert(KernAux_File_puts(&my_file.file, hello) == true);
|
||||
|
||||
// Write null character to the file
|
||||
assert(KernAux_File_putc(&my_file.file, '\0') != KERNAUX_EOF);
|
||||
|
||||
// Write random data to the file
|
||||
count = sizeof(data);
|
||||
assert(KernAux_File_write(&my_file.file, data, &count) == true);
|
||||
assert(count == sizeof(data));
|
||||
|
||||
// Seek to the beginning of the file
|
||||
KernAux_File_rewind(&my_file.file);
|
||||
|
||||
// Read a line from the file
|
||||
count = 14;
|
||||
assert(KernAux_File_gets(&my_file.file, tmp_buffer, &count) == true);
|
||||
assert(count == 14);
|
||||
|
||||
// Read random data from the file
|
||||
count = 6;
|
||||
assert(KernAux_File_read(&my_file.file, &tmp_buffer[14], &count) == true);
|
||||
assert(count == 6);
|
||||
|
||||
// Read a single character from the file
|
||||
assert(KernAux_File_getc(&my_file.file) == KERNAUX_EOF);
|
||||
|
||||
|
||||
assert(strcmp(&buffer[0], hello) == 0);
|
||||
assert(memcmp(&buffer[14], data, sizeof(data)) == 0);
|
||||
assert(strcmp(&tmp_buffer[0], hello) == 0);
|
||||
assert(memcmp(&tmp_buffer[14], data, sizeof(data)) == 0);
|
||||
}
|
|
@ -1,6 +1,3 @@
|
|||
#define KERNAUX_ACCESS_PROTECTED
|
||||
|
||||
#include <kernaux/generic/file.h>
|
||||
#include <kernaux/printf.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
@ -10,26 +7,23 @@
|
|||
|
||||
#define BUFFER_SIZE 1024
|
||||
|
||||
static const char *const data = "foobar";
|
||||
|
||||
static char buffer[BUFFER_SIZE];
|
||||
static size_t buffer_index = 0;
|
||||
|
||||
static int my_putc(__attribute__((unused)) void *const file, unsigned char c)
|
||||
static void my_putchar(const char chr, void *arg)
|
||||
{
|
||||
assert(arg == data);
|
||||
if (buffer_index >= BUFFER_SIZE) abort();
|
||||
buffer[buffer_index++] = c;
|
||||
return 1;
|
||||
buffer[buffer_index++] = chr;
|
||||
}
|
||||
|
||||
static const struct KernAux_File file = {
|
||||
.putc = my_putc,
|
||||
.puts = NULL,
|
||||
.write = NULL,
|
||||
};
|
||||
|
||||
void example_main()
|
||||
{
|
||||
const int result = kernaux_fprintf(
|
||||
&file,
|
||||
my_putchar,
|
||||
(void*)data,
|
||||
"Hello, %s! Session ID: %u.",
|
||||
"Alex",
|
||||
123
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
#define KERNAUX_ACCESS_PROTECTED
|
||||
|
||||
#include <kernaux/generic/file.h>
|
||||
#include <kernaux/printf.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
@ -10,27 +7,23 @@
|
|||
|
||||
#define BUFFER_SIZE 1024
|
||||
|
||||
static const char *const data = "foobar";
|
||||
|
||||
static char buffer[BUFFER_SIZE];
|
||||
static size_t buffer_index = 0;
|
||||
|
||||
static int my_putc(__attribute__((unused)) void *const file, unsigned char c)
|
||||
static void my_putchar(const char chr, void *arg)
|
||||
{
|
||||
assert(arg == data);
|
||||
if (buffer_index >= BUFFER_SIZE) abort();
|
||||
buffer[buffer_index++] = c;
|
||||
return 1;
|
||||
buffer[buffer_index++] = chr;
|
||||
}
|
||||
|
||||
static const struct KernAux_File file = {
|
||||
.putc = my_putc,
|
||||
.puts = NULL,
|
||||
.write = NULL,
|
||||
};
|
||||
|
||||
static int my_printf(const char *const format, ...)
|
||||
{
|
||||
va_list va;
|
||||
va_start(va, format);
|
||||
const int result = kernaux_vfprintf(&file, format, va);
|
||||
const int result = kernaux_vfprintf(my_putchar, (void*)data, format, va);
|
||||
va_end(va);
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@ nobase_include_HEADERS = \
|
|||
kernaux/macro/packing_start.run \
|
||||
kernaux/macro/packing_end.run \
|
||||
kernaux/version.h \
|
||||
kernaux/generic/file.h \
|
||||
kernaux/generic/malloc.h \
|
||||
kernaux/generic/mutex.h
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
#include <kernaux/macro.h>
|
||||
#include <kernaux/version.h>
|
||||
|
||||
#include <kernaux/generic/file.h>
|
||||
#include <kernaux/generic/malloc.h>
|
||||
#include <kernaux/generic/mutex.h>
|
||||
|
||||
|
|
|
@ -5,8 +5,6 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <kernaux/generic/file.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
|
|
|
@ -5,20 +5,19 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <kernaux/generic/file.h>
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/**
|
||||
* Tiny [v]fprintf implementation
|
||||
* \param file An output file
|
||||
* \param out An output function
|
||||
* \param data Additional data for the 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
|
||||
*/
|
||||
int kernaux_fprintf(KernAux_File file, const char* format, ...);
|
||||
int kernaux_vfprintf(KernAux_File file, const char* format, va_list va);
|
||||
int kernaux_fprintf(void (*out)(char, void*), void *data, const char* format, ...);
|
||||
int kernaux_vfprintf(void (*out)(char, void*), void *data, const char* format, va_list va);
|
||||
|
||||
/**
|
||||
* Tiny [v]snprintf implementation
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
#include <kernaux/assert.h>
|
||||
#include <kernaux/cmdline.h>
|
||||
#include <kernaux/generic/file.h>
|
||||
#include <kernaux/macro.h>
|
||||
|
||||
#include <stddef.h>
|
||||
|
@ -27,7 +26,6 @@ static bool kernaux_cmdline_common(
|
|||
char arg_terminator,
|
||||
char **argv,
|
||||
char *buffer,
|
||||
KernAux_File file,
|
||||
size_t *arg_idxs,
|
||||
size_t arg_count_max,
|
||||
size_t buffer_size
|
||||
|
@ -42,7 +40,6 @@ static bool kernaux_cmdline_iter(
|
|||
char arg_terminator,
|
||||
char **argv,
|
||||
char *buffer,
|
||||
KernAux_File file,
|
||||
size_t *arg_idxs,
|
||||
size_t arg_count_max,
|
||||
size_t buffer_size
|
||||
|
@ -76,7 +73,6 @@ bool kernaux_cmdline(
|
|||
argv,
|
||||
buffer,
|
||||
NULL,
|
||||
NULL,
|
||||
arg_count_max,
|
||||
buffer_size
|
||||
);
|
||||
|
@ -100,7 +96,6 @@ bool kernaux_cmdline_common(
|
|||
char arg_terminator,
|
||||
char **const argv,
|
||||
char *const buffer,
|
||||
const KernAux_File file,
|
||||
size_t *const arg_idxs,
|
||||
const size_t arg_count_max,
|
||||
const size_t buffer_size
|
||||
|
@ -128,7 +123,6 @@ bool kernaux_cmdline_common(
|
|||
arg_terminator,
|
||||
argv,
|
||||
buffer,
|
||||
file,
|
||||
arg_idxs,
|
||||
arg_count_max,
|
||||
buffer_size
|
||||
|
@ -159,11 +153,6 @@ fail:
|
|||
if (buffer) { \
|
||||
buffer[*buffer_or_file_pos] = char; \
|
||||
} \
|
||||
if (file) { \
|
||||
if (KernAux_File_putc(file, char) == KERNAUX_EOF) { \
|
||||
FAIL("EOF or buffer overflow"); \
|
||||
} \
|
||||
} \
|
||||
++(*buffer_or_file_pos); \
|
||||
} while (0)
|
||||
|
||||
|
@ -191,11 +180,6 @@ fail:
|
|||
argv[*argc] = &buffer[*buffer_or_file_pos]; \
|
||||
buffer[*buffer_or_file_pos] = char; \
|
||||
} \
|
||||
if (file) { \
|
||||
if (KernAux_File_putc(file, char) == KERNAUX_EOF) { \
|
||||
FAIL("EOF or buffer overflow"); \
|
||||
} \
|
||||
} \
|
||||
if (arg_idxs) { \
|
||||
arg_idxs[*argc] = *buffer_or_file_pos; \
|
||||
} \
|
||||
|
@ -212,7 +196,6 @@ bool kernaux_cmdline_iter(
|
|||
char arg_terminator,
|
||||
char **const argv,
|
||||
char *const buffer,
|
||||
const KernAux_File file,
|
||||
size_t *const arg_idxs,
|
||||
const size_t arg_count_max,
|
||||
const size_t buffer_size
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
#include <kernaux/assert.h>
|
||||
#include <kernaux/drivers/console.h>
|
||||
#include <kernaux/generic/file.h>
|
||||
|
||||
#ifdef ASM_I386
|
||||
#include <kernaux/asm/i386.h>
|
||||
|
@ -20,13 +19,7 @@
|
|||
#include <stddef.h>
|
||||
|
||||
#ifdef WITH_PRINTF
|
||||
static int file_putc(void *file, unsigned char c);
|
||||
|
||||
static const struct KernAux_File file = {
|
||||
.putc = file_putc,
|
||||
.puts = NULL,
|
||||
.write = NULL,
|
||||
};
|
||||
static void file_putc(char c, void *arg);
|
||||
#endif
|
||||
|
||||
void kernaux_drivers_console_putc(const char c __attribute__((unused)))
|
||||
|
@ -55,7 +48,7 @@ void kernaux_drivers_console_printf(const char *format, ...)
|
|||
|
||||
va_list va;
|
||||
va_start(va, format);
|
||||
kernaux_vfprintf(&file, format, va);
|
||||
kernaux_vfprintf(file_putc, NULL, format, va);
|
||||
va_end(va);
|
||||
}
|
||||
#endif
|
||||
|
@ -78,9 +71,8 @@ void kernaux_drivers_console_write(const char *const data, const size_t size)
|
|||
}
|
||||
|
||||
#ifdef WITH_PRINTF
|
||||
int file_putc(__attribute__((unused)) void *const file, const unsigned char c)
|
||||
void file_putc(char c, void *arg __attribute__((unused)))
|
||||
{
|
||||
kernaux_drivers_console_putc(c);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,138 +0,0 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <kernaux/assert.h>
|
||||
#include <kernaux/generic/file.h>
|
||||
#include <kernaux/macro.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
int KernAux_File_getc(const KernAux_File file)
|
||||
{
|
||||
KERNAUX_ASSERT(file);
|
||||
KERNAUX_ASSERT(file->getc);
|
||||
|
||||
return file->getc((void*)file);
|
||||
}
|
||||
|
||||
int KernAux_File_putc(const KernAux_File file, const int c)
|
||||
{
|
||||
KERNAUX_ASSERT(file);
|
||||
KERNAUX_ASSERT(file->putc);
|
||||
|
||||
return file->putc((void*)file, c);
|
||||
}
|
||||
|
||||
bool KernAux_File_gets(
|
||||
const KernAux_File file,
|
||||
void *const buffer,
|
||||
size_t *const count
|
||||
) {
|
||||
KERNAUX_ASSERT(file);
|
||||
KERNAUX_ASSERT(buffer);
|
||||
KERNAUX_ASSERT(count);
|
||||
// Reserve space for the terminating null character
|
||||
KERNAUX_ASSERT(*count > 0);
|
||||
|
||||
// Common implementation
|
||||
if (*count == 1) {
|
||||
*((char*)buffer) = '\0';
|
||||
return true;
|
||||
}
|
||||
|
||||
// Inherited implementation
|
||||
if (file->gets) return file->gets((void*)file, buffer, count);
|
||||
|
||||
// Default implementation
|
||||
size_t index = 0;
|
||||
for (char *ss = buffer; index < *count; ++ss, ++index) {
|
||||
const int c = KernAux_File_getc(file);
|
||||
if (c == KERNAUX_EOF || c == '\0' || c == '\n') {
|
||||
*ss = '\0';
|
||||
*count = index + 1;
|
||||
return true;
|
||||
}
|
||||
*ss = c;
|
||||
}
|
||||
((char*)buffer)[index] = '\0';
|
||||
*count = index;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool KernAux_File_puts(const KernAux_File file, const char *const s)
|
||||
{
|
||||
KERNAUX_ASSERT(file);
|
||||
|
||||
// Common implementation
|
||||
if (!s) return true;
|
||||
|
||||
// Inherited implementation
|
||||
if (file->puts) return file->puts((void*)file, s);
|
||||
|
||||
// Default implementation
|
||||
for (const char *ss = s; *ss; ++ss) {
|
||||
if (KernAux_File_putc(file, *ss) == KERNAUX_EOF) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool KernAux_File_read(
|
||||
const KernAux_File file,
|
||||
void *const buffer,
|
||||
size_t *const count
|
||||
) {
|
||||
KERNAUX_ASSERT(file);
|
||||
KERNAUX_ASSERT(buffer);
|
||||
KERNAUX_ASSERT(count);
|
||||
|
||||
// Common implementation
|
||||
if (*count == 0) return true;
|
||||
|
||||
// Inherited implementation
|
||||
if (file->read) return file->read((void*)file, buffer, count);
|
||||
|
||||
// Default implementation
|
||||
size_t index = 0;
|
||||
for (char *ss = buffer; index < *count; ++ss, ++index) {
|
||||
const int c = KernAux_File_getc(file);
|
||||
if (c == KERNAUX_EOF) {
|
||||
*count = index;
|
||||
return false;
|
||||
}
|
||||
*ss = c;
|
||||
}
|
||||
*count = index;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool KernAux_File_write(
|
||||
const KernAux_File file,
|
||||
const void *const buffer,
|
||||
size_t *const count
|
||||
) {
|
||||
KERNAUX_ASSERT(file);
|
||||
KERNAUX_ASSERT(buffer);
|
||||
|
||||
// Common implementation
|
||||
if (*count == 0) return true;
|
||||
|
||||
// Inherited implementation
|
||||
if (file->write) return file->write((void*)file, buffer, count);
|
||||
|
||||
// Default implementation
|
||||
size_t index = 0;
|
||||
for (const char *ss = buffer; index < *count; ++ss, ++index) {
|
||||
if (KernAux_File_putc(file, *ss) == KERNAUX_EOF) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void KernAux_File_rewind(const KernAux_File file)
|
||||
{
|
||||
KERNAUX_ASSERT(file);
|
||||
KERNAUX_ASSERT(file->rewind);
|
||||
|
||||
file->rewind((void*)file);
|
||||
}
|
25
src/printf.c
25
src/printf.c
|
@ -14,7 +14,6 @@
|
|||
#endif
|
||||
|
||||
#include <kernaux/assert.h>
|
||||
#include <kernaux/generic/file.h>
|
||||
#include <kernaux/printf.h>
|
||||
#include <kernaux/printf_fmt.h>
|
||||
|
||||
|
@ -53,8 +52,6 @@ typedef struct {
|
|||
|
||||
static int _vsnprintf(out_fct_type out, char* buffer, const size_t maxlen, const char* format, va_list va);
|
||||
|
||||
static void file_putc(char c, void *arg);
|
||||
|
||||
static inline void _out_buffer(char character, void* buffer, size_t idx, size_t maxlen);
|
||||
static inline void _out_null(char character, void* buffer, size_t idx, size_t maxlen);
|
||||
static inline void _out_fct(char character, void* buffer, size_t idx, size_t maxlen);
|
||||
|
@ -72,25 +69,25 @@ static size_t _etoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, d
|
|||
* Implementations: main API *
|
||||
*****************************/
|
||||
|
||||
int kernaux_fprintf(const KernAux_File file, const char* format, ...)
|
||||
int kernaux_fprintf(void (*out)(char, void*), void *data, const char* format, ...)
|
||||
{
|
||||
KERNAUX_ASSERT(file);
|
||||
KERNAUX_ASSERT(out);
|
||||
KERNAUX_ASSERT(format);
|
||||
|
||||
va_list va;
|
||||
va_start(va, format);
|
||||
const out_fct_wrap_type out_fct_wrap = { file_putc, (void*)file };
|
||||
const out_fct_wrap_type out_fct_wrap = { out, data };
|
||||
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(const KernAux_File file, const char* format, va_list va)
|
||||
int kernaux_vfprintf(void (*out)(char, void*), void *data, const char* format, va_list va)
|
||||
{
|
||||
KERNAUX_ASSERT(file);
|
||||
KERNAUX_ASSERT(out);
|
||||
KERNAUX_ASSERT(format);
|
||||
|
||||
const out_fct_wrap_type out_fct_wrap = { file_putc, (void*)file };
|
||||
const out_fct_wrap_type out_fct_wrap = { out, data };
|
||||
return _vsnprintf(_out_fct, (char*)(uintptr_t)&out_fct_wrap, (size_t)-1, format, va);
|
||||
}
|
||||
|
||||
|
@ -126,16 +123,6 @@ int kernaux_sprintf(char* buffer, const char* format, ...)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/***************************
|
||||
* Implementation: file IO *
|
||||
***************************/
|
||||
|
||||
void file_putc(const char c, void *const arg)
|
||||
{
|
||||
KernAux_File file = arg;
|
||||
KernAux_File_putc(file, c);
|
||||
}
|
||||
|
||||
/******************************************
|
||||
* Implementation: main internal function *
|
||||
******************************************/
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
#define KERNAUX_ACCESS_PROTECTED
|
||||
|
||||
#include <kernaux/generic/file.h>
|
||||
#include <kernaux/printf.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
@ -15,10 +14,12 @@
|
|||
|
||||
#define BUFFER_SIZE 1024
|
||||
|
||||
static const char *const data = "foobar";
|
||||
|
||||
static char buffer[BUFFER_SIZE];
|
||||
static size_t buffer_index;
|
||||
|
||||
static int test_putc(__attribute__((unused)) void *const file, unsigned char c)
|
||||
static void test_putc(char c, __attribute__((unused)) void *arg)
|
||||
{
|
||||
if (buffer_index >= BUFFER_SIZE) {
|
||||
printf("Buffer overflow!\n");
|
||||
|
@ -26,15 +27,8 @@ static int test_putc(__attribute__((unused)) void *const file, unsigned char c)
|
|||
}
|
||||
|
||||
buffer[buffer_index++] = c;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const struct KernAux_File file = {
|
||||
.putc = test_putc,
|
||||
.puts = NULL,
|
||||
.write = NULL,
|
||||
};
|
||||
|
||||
static void test(const char *const expected, const char *const format, ...)
|
||||
{
|
||||
va_list va;
|
||||
|
@ -43,7 +37,7 @@ static void test(const char *const expected, const char *const format, ...)
|
|||
memset(buffer, '\0', sizeof(buffer));
|
||||
buffer_index = 0;
|
||||
va_start(va, format);
|
||||
result = kernaux_vfprintf(&file, format, va);
|
||||
result = kernaux_vfprintf(test_putc, (void*)data, format, va);
|
||||
va_end(va);
|
||||
assert((size_t)result == strlen(expected));
|
||||
assert(strcmp(expected, buffer) == 0);
|
||||
|
@ -61,7 +55,7 @@ void test_main()
|
|||
{
|
||||
memset(buffer, '\0', sizeof(buffer));
|
||||
buffer_index = 0;
|
||||
kernaux_fprintf(&file, "Hello, World!");
|
||||
kernaux_fprintf(test_putc, (void*)data, "Hello, World!");
|
||||
assert(strcmp("Hello, World!", buffer) == 0);
|
||||
|
||||
{% for case in cases %}
|
||||
|
|
Loading…
Reference in a new issue