#include "line-source.h" enum status line_source_init( struct line_source *src, const char *path, b_stream *stream) { memset(src, 0x0, sizeof *src); src->s_lines = b_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) { b_iterator_unref(src->s_linebuf_ptr); } if (src->s_lines) { b_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) { b_iterator_unref(src->s_linebuf_ptr); src->s_linebuf_ptr = NULL; } b_stringstream *s = b_stringstream_create(); b_status status = b_stream_read_line_s(src->s_stream, s); if (status == B_ERR_NO_DATA) { return ERR_EOF; } if (!B_OK(status)) { return ERR_INTERNAL_FAILURE; } b_string *line = b_string_create(); b_string_replace_all_with_stringstream(line, s); b_stringstream_unref(s); b_array_append(src->s_lines, line); b_string_unref(line); src->s_linebuf = line; src->s_linebuf_ptr = b_iterator_begin(src->s_linebuf); return SUCCESS; } static int peek(struct line_source *src) { enum status status = SUCCESS; if (!src->s_linebuf_ptr || !b_iterator_is_valid(src->s_linebuf_ptr)) { status = refill_linebuf(src); } if (status != SUCCESS) { return -status; } if (b_string_get_size(src->s_linebuf, B_STRLEN_NORMAL) == 0) { return -ERR_EOF; } b_wchar c = b_iterator_get_value(src->s_linebuf_ptr).v_int; return c; } static int advance(struct line_source *src) { enum status status = SUCCESS; if (!b_iterator_is_valid(src->s_linebuf_ptr)) { status = refill_linebuf(src); } if (status != SUCCESS) { return -status; } if (b_string_get_size(src->s_linebuf, B_STRLEN_NORMAL) == 0) { return -ERR_EOF; } b_wchar c = b_iterator_get_value(src->s_linebuf_ptr).v_int; b_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; } b_wchar line_source_peekc(struct line_source *src) { return peek(src); } b_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 b_string **out) { if (row == 0) { return ERR_INVALID_ARGUMENT; } row--; if (row >= b_array_size(src->s_lines)) { return ERR_EOF; } b_string *line = b_array_at(src->s_lines, row); *out = line; return SUCCESS; } bool line_source_input_available(struct line_source *src) { return src->s_linebuf_ptr && b_iterator_is_valid(src->s_linebuf_ptr); }