Remove generic file API (#108)

This commit is contained in:
Alex Kotov 2022-11-26 23:04:36 +04:00 committed by GitHub
parent 123bddd19c
commit 15ed72fee5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 38 additions and 380 deletions

View File

@ -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
View File

@ -107,7 +107,6 @@
/examples/assert
/examples/cmdline
/examples/generic_file
/examples/generic_malloc
/examples/generic_mutex
/examples/macro_bits

View File

@ -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>

View File

@ -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

View File

@ -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* **?.?.?**)

View File

@ -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

View File

@ -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 #
##################

View File

@ -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);
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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>

View File

@ -5,8 +5,6 @@
extern "C" {
#endif
#include <kernaux/generic/file.h>
#include <stdbool.h>
#include <stddef.h>

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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 *
******************************************/

View File

@ -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 %}