165 lines
2.9 KiB
C
165 lines
2.9 KiB
C
#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);
|
|
}
|