2025-05-08 20:28:24 +01:00
|
|
|
#include <blue/object/array.h>
|
|
|
|
|
#include <blue/object/string.h>
|
|
|
|
|
#include <errno.h>
|
2024-11-13 21:36:37 +00:00
|
|
|
#include <ivy/file.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
2025-05-08 20:28:24 +01:00
|
|
|
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(
|
2024-11-13 21:36:37 +00:00
|
|
|
struct ivy_line_source *src, char *buf, size_t count, size_t *nr_read,
|
|
|
|
|
const char *prompt)
|
|
|
|
|
{
|
|
|
|
|
if (!count) {
|
|
|
|
|
*nr_read = 0;
|
|
|
|
|
return IVY_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct ivy_file *f = (struct ivy_file *)src;
|
2024-12-13 17:21:14 +00:00
|
|
|
if (!fgets(buf, (int)count, f->f_fp)) {
|
2024-11-13 21:36:37 +00:00
|
|
|
return feof(f->f_fp) ? IVY_ERR_EOF : IVY_ERR_IO_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-08 20:28:24 +01:00
|
|
|
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);
|
|
|
|
|
|
2024-11-13 21:36:37 +00:00
|
|
|
*nr_read = strlen(buf);
|
|
|
|
|
return IVY_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-08 20:28:24 +01:00
|
|
|
enum ivy_status ivy_file_open(const char *path, struct ivy_file **out)
|
2024-11-13 21:36:37 +00:00
|
|
|
{
|
2025-05-08 20:28:24 +01:00
|
|
|
FILE *fp = fopen(path, "r");
|
|
|
|
|
if (!fp) {
|
|
|
|
|
return ivy_status_from_errno(errno);
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-13 21:36:37 +00:00
|
|
|
struct ivy_file *file = malloc(sizeof *file);
|
|
|
|
|
if (!file) {
|
2025-05-08 20:28:24 +01:00
|
|
|
fclose(fp);
|
|
|
|
|
return IVY_ERR_NO_MEMORY;
|
2024-11-13 21:36:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
memset(file, 0x0, sizeof *file);
|
|
|
|
|
|
2025-05-08 20:28:24 +01:00
|
|
|
file->f_base.s_get_name = get_name;
|
|
|
|
|
file->f_base.s_get_row = get_row;
|
|
|
|
|
file->f_base.s_readline = readline;
|
2024-11-13 21:36:37 +00:00
|
|
|
file->f_fp = fp;
|
2025-05-08 20:28:24 +01:00
|
|
|
file->f_path = b_strdup(path);
|
|
|
|
|
file->f_lines = b_array_create();
|
2024-11-13 21:36:37 +00:00
|
|
|
|
2025-05-08 20:28:24 +01:00
|
|
|
*out = file;
|
|
|
|
|
|
|
|
|
|
return IVY_OK;
|
2024-11-13 21:36:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ivy_file_close(struct ivy_file *file)
|
|
|
|
|
{
|
2025-05-08 20:28:24 +01:00
|
|
|
b_array_release(file->f_lines);
|
|
|
|
|
free(file->f_path);
|
2024-11-13 21:36:37 +00:00
|
|
|
fclose(file->f_fp);
|
|
|
|
|
free(file);
|
|
|
|
|
}
|