117 lines
2.2 KiB
C
117 lines
2.2 KiB
C
#include "file.h"
|
|
|
|
#include "line-source.h"
|
|
|
|
#include <errno.h>
|
|
#include <fx/collections/array.h>
|
|
#include <fx/string.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
static enum bshell_status get_name(
|
|
struct line_source *src,
|
|
char *buf,
|
|
size_t count,
|
|
size_t *nr_read)
|
|
{
|
|
struct file *f = (struct file *)src;
|
|
*nr_read = snprintf(buf, count, "%s", f->f_path);
|
|
return BSHELL_SUCCESS;
|
|
}
|
|
|
|
static enum bshell_status get_row(
|
|
struct line_source *src,
|
|
size_t row,
|
|
char *buf,
|
|
size_t count,
|
|
size_t *nr_read)
|
|
{
|
|
struct file *f = (struct file *)src;
|
|
size_t nr_rows = fx_array_size(f->f_lines);
|
|
|
|
if (row > nr_rows) {
|
|
return BSHELL_ERR_EOF;
|
|
}
|
|
|
|
fx_string *line = fx_array_at(f->f_lines, row - 1);
|
|
|
|
const char *line_str = fx_string_get_cstr(line);
|
|
size_t line_len = fx_string_get_size(line, FX_STRLEN_NORMAL);
|
|
size_t copy_len = fx_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 BSHELL_SUCCESS;
|
|
}
|
|
|
|
static enum bshell_status readline(
|
|
struct line_source *src,
|
|
fx_stringstream *out)
|
|
{
|
|
struct file *f = (struct file *)src;
|
|
fx_wchar c = FX_WCHAR_INVALID;
|
|
size_t nr_read = 0;
|
|
|
|
while (1) {
|
|
fx_status status = fx_stream_read_char(f->f_strp, &c);
|
|
if (!FX_OK(status)) {
|
|
break;
|
|
}
|
|
|
|
fx_stream_write_char(out, c);
|
|
nr_read++;
|
|
|
|
if (c == '\n') {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (nr_read == 0) {
|
|
return BSHELL_ERR_EOF;
|
|
}
|
|
|
|
return BSHELL_SUCCESS;
|
|
}
|
|
|
|
enum bshell_status file_open(const char *path, struct file **out)
|
|
{
|
|
FILE *fp = fopen(path, "r");
|
|
if (!fp) {
|
|
return bshell_status_from_errno(errno);
|
|
}
|
|
|
|
fx_stream *strp = fx_stream_open_fp(fp);
|
|
|
|
struct file *file = malloc(sizeof *file);
|
|
if (!file) {
|
|
fclose(fp);
|
|
return BSHELL_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_strp = strp;
|
|
file->f_path = fx_strdup(path);
|
|
file->f_lines = fx_array_create();
|
|
|
|
*out = file;
|
|
|
|
return BSHELL_SUCCESS;
|
|
}
|
|
|
|
void file_close(struct file *file)
|
|
{
|
|
fx_stream_unref(file->f_strp);
|
|
fx_array_unref(file->f_lines);
|
|
free(file->f_path);
|
|
fclose(file->f_fp);
|
|
free(file);
|
|
}
|