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,
|
|
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);
|
|
}
|