162 lines
3.1 KiB
C
162 lines
3.1 KiB
C
#include <mie/parse/line-source.h>
|
|
|
|
enum mie_status mie_line_source_init(
|
|
struct mie_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 MIE_ERR_NO_MEMORY;
|
|
}
|
|
|
|
src->s_stream = stream;
|
|
src->s_path = path;
|
|
src->s_cursor.c_col = 1;
|
|
src->s_cursor.c_row = 1;
|
|
|
|
return MIE_SUCCESS;
|
|
}
|
|
|
|
void mie_line_source_cleanup(struct mie_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 *mie_line_source_get_path(const struct mie_line_source *src)
|
|
{
|
|
return src->s_path;
|
|
}
|
|
|
|
const struct mie_file_cell *mie_line_source_get_cursor(
|
|
const struct mie_line_source *src)
|
|
{
|
|
return &src->s_cursor;
|
|
}
|
|
|
|
static enum mie_status refill_linebuf(struct mie_line_source *src)
|
|
{
|
|
if (!src->s_stream) {
|
|
return MIE_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 MIE_ERR_EOF;
|
|
}
|
|
|
|
if (!B_OK(status)) {
|
|
return MIE_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 MIE_SUCCESS;
|
|
}
|
|
|
|
static int peek(struct mie_line_source *src)
|
|
{
|
|
enum mie_status status = MIE_SUCCESS;
|
|
|
|
if (!src->s_linebuf_ptr || !b_iterator_is_valid(src->s_linebuf_ptr)) {
|
|
status = refill_linebuf(src);
|
|
}
|
|
|
|
if (status != MIE_SUCCESS) {
|
|
return -status;
|
|
}
|
|
|
|
if (b_string_get_size(src->s_linebuf, B_STRLEN_NORMAL) == 0) {
|
|
return -MIE_ERR_EOF;
|
|
}
|
|
|
|
b_wchar c = b_iterator_get_value(src->s_linebuf_ptr).v_int;
|
|
return c;
|
|
}
|
|
|
|
static int advance(struct mie_line_source *src)
|
|
{
|
|
enum mie_status status = MIE_SUCCESS;
|
|
|
|
if (!b_iterator_is_valid(src->s_linebuf_ptr)) {
|
|
status = refill_linebuf(src);
|
|
}
|
|
|
|
if (status != MIE_SUCCESS) {
|
|
return -status;
|
|
}
|
|
|
|
if (b_string_get_size(src->s_linebuf, B_STRLEN_NORMAL) == 0) {
|
|
return -MIE_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 mie_line_source_peekc(struct mie_line_source *src)
|
|
{
|
|
return peek(src);
|
|
}
|
|
|
|
b_wchar mie_line_source_getc(struct mie_line_source *src)
|
|
{
|
|
return advance(src);
|
|
}
|
|
|
|
enum mie_status mie_line_source_get_row(
|
|
struct mie_line_source *src, size_t row, const b_string **out)
|
|
{
|
|
if (row == 0) {
|
|
return MIE_ERR_INVALID_ARGUMENT;
|
|
}
|
|
|
|
row--;
|
|
|
|
if (row >= b_array_size(src->s_lines)) {
|
|
return MIE_ERR_EOF;
|
|
}
|
|
|
|
b_string *line = b_array_at(src->s_lines, row);
|
|
*out = line;
|
|
|
|
return MIE_SUCCESS;
|
|
}
|
|
|
|
bool mie_line_source_input_available(struct mie_line_source *src)
|
|
{
|
|
return src->s_linebuf_ptr && b_iterator_is_valid(src->s_linebuf_ptr);
|
|
}
|