Files
rosetta/toolchain/xpcg/line-source.c

165 lines
2.9 KiB
C
Raw Normal View History

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