#include #include #include #include #include #include #include static enum bshell_status get_name( struct bshell_line_source *src, char *buf, size_t count, size_t *nr_read) { struct bshell_file *f = (struct bshell_file *)src; *nr_read = snprintf(buf, count, "%s", f->f_path); return BSHELL_SUCCESS; } static enum bshell_status get_row( struct bshell_line_source *src, size_t row, char *buf, size_t count, size_t *nr_read) { struct bshell_file *f = (struct bshell_file *)src; size_t nr_rows = fx_array_get_size(f->f_lines); if (row > nr_rows) { return BSHELL_ERR_EOF; } fx_value *line_v = fx_array_get_ref(f->f_lines, row - 1); fx_string *line = NULL; fx_value_get_object(line_v, &line); 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 bshell_line_source *src, fx_stringstream *out) { struct bshell_file *f = (struct bshell_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 bshell_file_open(const char *path, struct bshell_file **out) { FILE *fp = fopen(path, "r"); if (!fp) { return bshell_status_from_errno(errno); } fx_stream *strp = fx_stream_open_fp(fp); struct bshell_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 bshell_file_close(struct bshell_file *file) { fx_stream_unref(file->f_strp); fx_array_unref(file->f_lines); free(file->f_path); fclose(file->f_fp); free(file); }