mirror of
https://github.com/tailix/libkernaux.git
synced 2024-11-13 11:04:27 -05:00
File input (#107)
This commit is contained in:
parent
ab1773964c
commit
123bddd19c
5 changed files with 179 additions and 45 deletions
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)))
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue