#include "line-source.h" enum status line_source_init( struct line_source *src, const char *path, fx_stream *stream) { memset(src, 0x0, sizeof *src); src->s_lines = fx_array_create(); if (!src->s_lines) { return ERR_NO_MEMORY; } src->s_stream = stream; src->s_path = path; src->s_cursor.c_col = 1; src->s_cursor.c_row = 1; return SUCCESS; } void line_source_cleanup(struct line_source *src) { if (src->s_linebuf_ptr) { fx_iterator_unref(src->s_linebuf_ptr); } if (src->s_lines) { fx_array_unref(src->s_lines); } memset(src, 0x0, sizeof *src); } const char *line_source_get_path(const struct line_source *src) { return src->s_path; } const struct file_cell *line_source_get_cursor(const struct line_source *src) { return &src->s_cursor; } static enum status refill_linebuf(struct line_source *src) { if (!src->s_stream) { return ERR_EOF; } if (src->s_linebuf_ptr) { fx_iterator_unref(src->s_linebuf_ptr); src->s_linebuf_ptr = NULL; } fx_stringstream *s = fx_stringstream_create(); fx_status status = fx_stream_read_line_s(src->s_stream, s); if (status == FX_ERR_NO_DATA) { return ERR_EOF; } if (!FX_OK(status)) { return ERR_INTERNAL_FAILURE; } fx_string *line = fx_string_create(); fx_string_replace_all_with_stringstream(line, s); fx_stringstream_unref(s); fx_array_append(src->s_lines, line); fx_string_unref(line); src->s_linebuf = line; src->s_linebuf_ptr = fx_iterator_begin(src->s_linebuf); return SUCCESS; } static int peek(struct line_source *src) { enum status status = SUCCESS; if (!src->s_linebuf_ptr || !fx_iterator_is_valid(src->s_linebuf_ptr)) { status = refill_linebuf(src); } if (status != SUCCESS) { return -status; } if (fx_string_get_size(src->s_linebuf, FX_STRLEN_NORMAL) == 0) { return -ERR_EOF; } fx_wchar c = fx_iterator_get_value(src->s_linebuf_ptr).v_int; return c; } static int advance(struct line_source *src) { enum status status = SUCCESS; if (!fx_iterator_is_valid(src->s_linebuf_ptr)) { status = refill_linebuf(src); } if (status != SUCCESS) { return -status; } if (fx_string_get_size(src->s_linebuf, FX_STRLEN_NORMAL) == 0) { return -ERR_EOF; } fx_wchar c = fx_iterator_get_value(src->s_linebuf_ptr).v_int; fx_iterator_move_next(src->s_linebuf_ptr); src->s_cursor.c_col++; if (c == '\n') { src->s_cursor.c_col = 1; src->s_cursor.c_row++; } return c; } fx_wchar line_source_peekc(struct line_source *src) { return peek(src); } fx_wchar line_source_getc(struct line_source *src) { return advance(src); } enum status line_source_get_row( struct line_source *src, size_t row, const fx_string **out) { if (row == 0) { return ERR_INVALID_ARGUMENT; } row--; if (row >= fx_array_size(src->s_lines)) { return ERR_EOF; } fx_string *line = fx_array_at(src->s_lines, row); *out = line; return SUCCESS; } bool line_source_input_available(struct line_source *src) { return src->s_linebuf_ptr && fx_iterator_is_valid(src->s_linebuf_ptr); }