From bb55bee7f83b8ba14c61394b1f977addadd59f56 Mon Sep 17 00:00:00 2001 From: Max Wash Date: Thu, 8 May 2025 20:28:24 +0100 Subject: [PATCH] common: implement s_get_row and s_get_name in ivy_file --- common/file.c | 64 ++++++++++++++++++++++++++++++++++--- common/include/ivy/file.h | 6 +++- common/include/ivy/status.h | 1 + common/status.c | 12 +++++++ 4 files changed, 77 insertions(+), 6 deletions(-) diff --git a/common/file.c b/common/file.c index 35769c3..46c931e 100644 --- a/common/file.c +++ b/common/file.c @@ -1,8 +1,44 @@ +#include +#include +#include #include #include #include -static enum ivy_status file_readline( +static enum ivy_status get_name( + struct ivy_line_source *src, char *buf, size_t count, size_t *nr_read) +{ + struct ivy_file *f = (struct ivy_file *)src; + *nr_read = snprintf(buf, count, "%s", f->f_path); + return IVY_OK; +} + +static enum ivy_status get_row( + struct ivy_line_source *src, size_t row, char *buf, size_t count, + size_t *nr_read) +{ + struct ivy_file *f = (struct ivy_file *)src; + size_t nr_rows = b_array_size(f->f_lines); + + if (row > nr_rows) { + return IVY_ERR_EOF; + } + + b_string *line = B_STRING(b_array_at(f->f_lines, row - 1)); + + const char *line_str = b_string_ptr(line); + size_t line_len = b_string_get_size(line, B_STRLEN_NORMAL); + size_t copy_len = b_min(ulong, count, line_len); + + memcpy(buf, line_str, copy_len); + buf[copy_len] = 0; + buf[strcspn(buf, "\n")] = 0; + *nr_read = copy_len; + + return IVY_OK; +} + +static enum ivy_status readline( struct ivy_line_source *src, char *buf, size_t count, size_t *nr_read, const char *prompt) { @@ -16,27 +52,45 @@ static enum ivy_status file_readline( return feof(f->f_fp) ? IVY_ERR_EOF : IVY_ERR_IO_FAILURE; } + b_string *line_str = b_string_create_from_cstr(buf); + b_array_append(f->f_lines, B_OBJECT(line_str)); + b_string_release(line_str); + *nr_read = strlen(buf); return IVY_OK; } -struct ivy_file *ivy_file_from_fp(FILE *fp) +enum ivy_status ivy_file_open(const char *path, struct ivy_file **out) { + FILE *fp = fopen(path, "r"); + if (!fp) { + return ivy_status_from_errno(errno); + } + struct ivy_file *file = malloc(sizeof *file); if (!file) { - return NULL; + fclose(fp); + return IVY_ERR_NO_MEMORY; } memset(file, 0x0, sizeof *file); + file->f_base.s_get_name = get_name; + file->f_base.s_get_row = get_row; + file->f_base.s_readline = readline; file->f_fp = fp; - file->f_base.s_readline = file_readline; + file->f_path = b_strdup(path); + file->f_lines = b_array_create(); - return file; + *out = file; + + return IVY_OK; } void ivy_file_close(struct ivy_file *file) { + b_array_release(file->f_lines); + free(file->f_path); fclose(file->f_fp); free(file); } diff --git a/common/include/ivy/file.h b/common/include/ivy/file.h index f50ee1e..76905f7 100644 --- a/common/include/ivy/file.h +++ b/common/include/ivy/file.h @@ -5,12 +5,16 @@ #include #include +struct b_array; + struct ivy_file { struct ivy_line_source f_base; + struct b_array *f_lines; + char *f_path; FILE *f_fp; }; -IVY_API struct ivy_file *ivy_file_from_fp(FILE *fp); +IVY_API enum ivy_status ivy_file_open(const char *path, struct ivy_file **out); IVY_API void ivy_file_close(struct ivy_file *file); #endif diff --git a/common/include/ivy/status.h b/common/include/ivy/status.h index b2ebc34..ac1dfa7 100644 --- a/common/include/ivy/status.h +++ b/common/include/ivy/status.h @@ -21,5 +21,6 @@ enum ivy_status { IVY_API const char *ivy_status_to_string(enum ivy_status status); IVY_API enum ivy_status ivy_status_from_b_status(enum b_status status); +IVY_API enum ivy_status ivy_status_from_errno(int err); #endif diff --git a/common/status.c b/common/status.c index 6ad2db4..e37da87 100644 --- a/common/status.c +++ b/common/status.c @@ -1,4 +1,5 @@ #include +#include #include #define ENUM_STR(x) \ @@ -34,3 +35,14 @@ enum ivy_status ivy_status_from_b_status(enum b_status status) return IVY_ERR_INTERNAL_FAILURE; } } + +enum ivy_status ivy_status_from_errno(int err) +{ + switch (err) { + ENUM_CONVERT(0, IVY_OK); + ENUM_CONVERT(ENOENT, IVY_ERR_NO_ENTRY); + ENUM_CONVERT(ENOMEM, IVY_ERR_NO_MEMORY); + default: + return IVY_ERR_INTERNAL_FAILURE; + } +}