File input (#107)

This commit is contained in:
Alex Kotov 2022-06-30 23:07:10 +03:00 committed by GitHub
parent ab1773964c
commit 123bddd19c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 179 additions and 45 deletions

View File

@ -29,22 +29,37 @@ struct MyFile MyFile_create(char *ptr, size_t size);
//===========
#include <kernaux/generic/file.h>
#include <kernaux/macro.h>
#include <stddef.h>
static int MyFile_putc(void *file, unsigned char c);
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.puts = NULL; // "puts" has a default implementation
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;
@ -53,10 +68,18 @@ int MyFile_putc(void *const file, const unsigned char 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>
@ -65,31 +88,47 @@ 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
{
const int result = KernAux_File_puts(&my_file.file, hello);
assert(result != KERNAUX_EOF);
}
assert(KernAux_File_puts(&my_file.file, hello) == true);
// Write null character to the file
{
const int result = KernAux_File_putc(&my_file.file, '\0');
assert(result != KERNAUX_EOF);
}
char data[6];
memset(data, 0xff, sizeof(data));
assert(KernAux_File_putc(&my_file.file, '\0') != KERNAUX_EOF);
// Write random data to the file
{
const int result = KernAux_File_write(&my_file.file, data, sizeof(data));
assert(result != KERNAUX_EOF);
}
count = sizeof(data);
assert(KernAux_File_write(&my_file.file, data, &count) == true);
assert(count == sizeof(data));
assert(strcmp(buffer, hello) == 0);
// 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

@ -7,23 +7,34 @@ extern "C" {
#include <kernaux/macro.h>
#include <stdbool.h>
#include <stddef.h>
#define KERNAUX_EOF (-1)
typedef int (*KernAux_File_Putc) (void *file, unsigned char c);
typedef int (*KernAux_File_Puts) (void *file, const char *s);
typedef int (*KernAux_File_Write)(void *file, const void *buffer, size_t count);
typedef int (*KernAux_File_Getc) (void *file);
typedef int (*KernAux_File_Putc) (void *file, unsigned char c);
typedef bool (*KernAux_File_Gets) (void *file, void *buffer, size_t *count);
typedef bool (*KernAux_File_Puts) (void *file, const char *s);
typedef bool (*KernAux_File_Read) (void *file, void *buffer, size_t *count);
typedef bool (*KernAux_File_Write) (void *file, const void *buffer, size_t *count);
typedef void (*KernAux_File_Rewind)(void *file);
typedef const struct KernAux_File {
KernAux_File_Putc KERNAUX_PROTECTED_FIELD(putc);
KernAux_File_Puts KERNAUX_PROTECTED_FIELD(puts);
KernAux_File_Write KERNAUX_PROTECTED_FIELD(write);
KernAux_File_Getc KERNAUX_PROTECTED_FIELD(getc);
KernAux_File_Putc KERNAUX_PROTECTED_FIELD(putc);
KernAux_File_Gets KERNAUX_PROTECTED_FIELD(gets);
KernAux_File_Puts KERNAUX_PROTECTED_FIELD(puts);
KernAux_File_Read KERNAUX_PROTECTED_FIELD(read);
KernAux_File_Write KERNAUX_PROTECTED_FIELD(write);
KernAux_File_Rewind KERNAUX_PROTECTED_FIELD(rewind);
} *KernAux_File;
int KernAux_File_putc (KernAux_File file, int c);
int KernAux_File_puts (KernAux_File file, const char *s);
int KernAux_File_write(KernAux_File file, const void *buffer, size_t count);
int KernAux_File_getc (KernAux_File file);
int KernAux_File_putc (KernAux_File file, int c);
bool KernAux_File_gets (KernAux_File file, void *buffer, size_t *count);
bool KernAux_File_puts (KernAux_File file, const char *s);
bool KernAux_File_read (KernAux_File file, void *buffer, size_t *count);
bool KernAux_File_write (KernAux_File file, const void *buffer, size_t *count);
void KernAux_File_rewind(KernAux_File file);
#ifdef __cplusplus
}

View File

@ -8,6 +8,8 @@ extern "C" {
#include <stddef.h>
#include <stdint.h>
#define KERNAUX_EOF (-1)
#define KERNAUX_CONTAINER_OF(ptr, type, member) \
((type*)((uintptr_t)(ptr) - offsetof(type, member)))

View File

@ -5,6 +5,7 @@
#include <kernaux/assert.h>
#include <kernaux/cmdline.h>
#include <kernaux/generic/file.h>
#include <kernaux/macro.h>
#include <stddef.h>
#include <string.h>

View File

@ -4,9 +4,19 @@
#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);
@ -15,43 +25,114 @@ int KernAux_File_putc(const KernAux_File file, const int c)
return file->putc((void*)file, c);
}
int KernAux_File_puts(const KernAux_File file, const char *const s)
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 0;
if (!s) return true;
// Inherited implementation
if (file->puts) return file->puts((void*)file, s);
// Default implementation
size_t ccount = 0;
for (const char *ss = s; *ss; ++ss, ++ccount) {
if (KernAux_File_putc(file, *ss) == KERNAUX_EOF) return KERNAUX_EOF;
for (const char *ss = s; *ss; ++ss) {
if (KernAux_File_putc(file, *ss) == KERNAUX_EOF) return false;
}
const int icount = ccount;
return icount >= 0 ? icount : 0;
return true;
}
int KernAux_File_write(
bool KernAux_File_read(
const KernAux_File file,
const void *const buffer,
const size_t count
void *const buffer,
size_t *const count
) {
KERNAUX_ASSERT(file);
KERNAUX_ASSERT(buffer);
KERNAUX_ASSERT(count);
// Common implementation
if (count == 0 || !buffer) return 0;
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 ccount = 0;
for (const char *ss = buffer; ccount < count; ++ss, ++ccount) {
if (KernAux_File_putc(file, *ss) == KERNAUX_EOF) return KERNAUX_EOF;
size_t index = 0;
for (const char *ss = buffer; index < *count; ++ss, ++index) {
if (KernAux_File_putc(file, *ss) == KERNAUX_EOF) return false;
}
const int icount = ccount;
return icount >= 0 ? icount : 0;
return true;
}
void KernAux_File_rewind(const KernAux_File file)
{
KERNAUX_ASSERT(file);
KERNAUX_ASSERT(file->rewind);
file->rewind((void*)file);
}