Input/output stream#
To enable interaction with interpreter, basic input/output stream abstraction is needed. This implementation uses platform specific functions defined by architecture abstraction layer.
Input stream#
Input stream provides functionality of reading unsigned 8bit integers representing input characters. Implementation utilized lsp_stream_getchar_t function pointer provided during input stream initialization. Together with lsp_in_stream_read, used for reading next available input character, input stream contains single character buffer used for implementation of lsp_in_stream_peek functionality.
Output stream#
Output stream provides functionality regarding writing character data. It uses lsp_stream_putchar_t function pointer provided during output stream initialization. Available functions include:
lsp_out_stream_write
Write single character to output stream.
lsp_out_stream_write_str
Write null terminated character sequence.
lsp_out_stream_write_int
Write string representation of signed integer.
Source code#
stream.h#
#ifndef LISP16_STREAM_H
#define LISP16_STREAM_H
#include "mem.h"
typedef struct lsp_in_stream_t lsp_in_stream_t;
typedef struct lsp_out_stream_t lsp_out_stream_t;
typedef lsp_int16_t (*lsp_stream_getchar_t)(lsp_in_stream_t *s);
typedef lsp_int16_t (*lsp_stream_putchar_t)(lsp_out_stream_t *s, lsp_int16_t v);
struct lsp_in_stream_t {
// internal
lsp_stream_getchar_t getchar;
lsp_bool_t next_available;
lsp_uint8_t next_value;
lsp_status_t next_status;
};
struct lsp_out_stream_t {
// internal
lsp_stream_putchar_t putchar;
};
typedef struct {
lsp_in_stream_t base;
// internal
lsp_mem_t *m;
lsp_addr_t str;
lsp_uint16_t pos;
} lsp_str_stream_t;
void lsp_in_stream_init(lsp_in_stream_t *s, lsp_stream_getchar_t getchar);
lsp_status_t lsp_in_stream_read(lsp_in_stream_t *s, lsp_uint8_t *v);
lsp_status_t lsp_in_stream_peek(lsp_in_stream_t *s, lsp_uint8_t *v);
void lsp_out_stream_init(lsp_out_stream_t *s, lsp_stream_putchar_t putchar);
lsp_status_t lsp_out_stream_write(lsp_out_stream_t *s, lsp_uint8_t v);
lsp_status_t lsp_out_stream_write_str(lsp_out_stream_t *s, char *str);
lsp_status_t lsp_out_stream_write_int(lsp_out_stream_t *s, lsp_int32_t v);
void lsp_str_stream_init(lsp_str_stream_t *s, lsp_mem_t *m, lsp_addr_t str);
#endif
stream.c#
#include "stream.h"
static lsp_int16_t str_getchar(lsp_in_stream_t *s) {
lsp_str_stream_t *ss = (lsp_str_stream_t *)s;
if (ss->pos >= lsp_mem_get_string_len(ss->m, ss->str))
return LSP_EOF;
return lsp_mem_get_string_data(ss->m, ss->str, ss->pos++);
}
void lsp_in_stream_init(lsp_in_stream_t *s, lsp_stream_getchar_t getchar) {
s->getchar = getchar;
s->next_available = false;
}
lsp_status_t lsp_in_stream_read(lsp_in_stream_t *s, lsp_uint8_t *v) {
if (s->next_available) {
s->next_available = false;
*v = s->next_value;
return s->next_status;
}
lsp_int16_t c = s->getchar(s);
*v = c;
return ((c == LSP_EOF) ? LSP_EOF : LSP_SUCCESS);
}
lsp_status_t lsp_in_stream_peek(lsp_in_stream_t *s, lsp_uint8_t *v) {
if (s->next_available) {
*v = s->next_value;
return s->next_status;
}
lsp_int16_t c = s->getchar(s);
s->next_available = true;
s->next_value = c;
s->next_status = ((c == LSP_EOF) ? LSP_EOF : LSP_SUCCESS);
*v = s->next_value;
return s->next_status;
}
void lsp_out_stream_init(lsp_out_stream_t *s, lsp_stream_putchar_t putchar) {
s->putchar = putchar;
}
lsp_status_t lsp_out_stream_write(lsp_out_stream_t *s, lsp_uint8_t v) {
if (s->putchar(s, v) == LSP_EOF)
return LSP_EOF;
return LSP_SUCCESS;
}
lsp_status_t lsp_out_stream_write_str(lsp_out_stream_t *s, char *str) {
while (*str) {
lsp_status_t status = lsp_out_stream_write(s, *(str++));
if (status != LSP_SUCCESS)
return status;
}
return LSP_SUCCESS;
}
lsp_status_t lsp_out_stream_write_int(lsp_out_stream_t *s, lsp_int32_t v) {
lsp_status_t status;
if (v < 0) {
v *= -1;
status = lsp_out_stream_write(s, '-');
if (status != LSP_SUCCESS)
return status;
}
lsp_uint8_t size = 0;
for (lsp_int32_t i = v; i; i /= 10)
size++;
if (size < 1)
size = 1;
for (lsp_uint8_t i = 0; i < size; ++i) {
lsp_int32_t temp = v;
for (lsp_uint8_t j = i; j < size - 1; ++j)
temp /= 10;
lsp_uint8_t digit = temp % 10;
status = lsp_out_stream_write(s, '0' + digit);
if (status != LSP_SUCCESS)
return status;
}
return LSP_SUCCESS;
}
void lsp_str_stream_init(lsp_str_stream_t *s, lsp_mem_t *m, lsp_addr_t str) {
lsp_in_stream_init((lsp_in_stream_t *)s, str_getchar);
s->m = m;
s->str = str;
s->pos = 0;
}