Files
bluelib/core/stream.c

931 lines
21 KiB
C
Raw Normal View History

#include "printf.h"
#include <blue/core/stream.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define B_TYPE_STDIO_STREAM (b_stdio_stream_get_type())
#define STREAM_DISPATCH_VIRTUAL(func, stream, ...) \
do { \
struct stream_data _stream; \
enum b_status status = stream_get_data(stream, &_stream); \
if (!B_OK(status)) { \
return status; \
} \
return func(&_stream, __VA_ARGS__); \
} while (0)
#define STREAM_DISPATCH_VIRTUAL_0(func, stream) \
do { \
struct stream_data _stream; \
enum b_status status = stream_get_data(stream, &_stream); \
if (!B_OK(status)) { \
return status; \
} \
return func(&_stream); \
} while (0)
#define IDX_STDIN 0
#define IDX_STDOUT 1
#define IDX_STDERR 2
B_DECLARE_TYPE(b_stdio_stream);
B_TYPE_CLASS_DECLARATION_BEGIN(b_stdio_stream)
B_TYPE_CLASS_DECLARATION_END(b_stdio_stream)
/*** PRIVATE DATA *************************************************************/
typedef enum b_stream_buffer_flags {
B_STREAM_BUFFER_F_NONE = 0x00u,
B_STREAM_BUFFER_F_DYNAMIC = 0x01u,
} b_stream_buffer_flags;
struct b_stream_p {
int *s_istack;
int s_add_indent;
size_t s_istack_ptr, s_istack_size;
void *s_ptr0, *s_ptr1;
};
struct b_stdio_stream_p {
FILE *s_fp;
};
struct b_stream_buffer_p {
b_stream_buffer_flags p_flags;
void *p_buf;
size_t p_buf_len;
};
struct stream_data {
b_stream *s_obj;
struct b_stream_p *s_private;
struct b_stream_cfg *s_cfg;
b_stream_class *s_ops;
};
static b_stream *stdio[] = {
[IDX_STDIN] = NULL,
[IDX_STDOUT] = NULL,
[IDX_STDERR] = NULL,
#if 0
[IDX_STDIN] = {
.s_mode = B_STREAM_READ,
.s_read = stdio_read,
.s_seek = stdio_seek,
.s_tell = stdio_tell,
.s_ptr0 = NULL, /* set to stdin (stdio.h) at runtime */
},
[IDX_STDOUT] = {
.s_mode = B_STREAM_WRITE,
.s_write = stdio_write,
.s_seek = stdio_seek,
.s_tell = stdio_tell,
.s_ptr0 = NULL, /* set to stdout (stdio.h) at runtime */
},
[IDX_STDERR] = {
.s_mode = B_STREAM_WRITE,
.s_write = stdio_write,
.s_seek = stdio_seek,
.s_tell = stdio_tell,
.s_ptr0 = NULL, /* set to stderr (stdio.h) at runtime */
},
#endif
};
/*** PRIVATE FUNCTIONS ********************************************************/
b_type b_stdio_stream_get_type(void);
static enum b_status stdio_read(b_stream *, unsigned char *, size_t, size_t *);
static enum b_status stdio_write(
b_stream *, const unsigned char *, size_t, size_t *);
static enum b_status stdio_seek(b_stream *, long long, b_stream_seek_origin);
static enum b_status stdio_tell(const b_stream *, size_t *);
static enum b_status stream_get_data(const b_stream *strp, struct stream_data *out)
{
out->s_obj = (b_stream *)strp;
return b_object_get_data(
strp, B_TYPE_STREAM, (void **)&out->s_private,
(void **)&out->s_cfg, (void **)&out->s_ops);
}
static int current_indent(struct stream_data *stream)
{
if (!stream->s_private->s_istack || !stream->s_private->s_istack_size) {
return 0;
}
return stream->s_private->s_istack[stream->s_private->s_istack_ptr];
}
static size_t stream_cursor(const struct stream_data *stream)
{
if (!stream || !stream->s_ops || !stream->s_ops->s_tell) {
return B_NPOS;
}
size_t p = B_NPOS;
b_status status = stream->s_ops->s_tell(stream->s_obj, &p);
if (!B_OK(status)) {
return B_NPOS;
}
return p;
}
static enum b_status stream_seek(
struct stream_data *stream, long long offset, b_stream_seek_origin origin)
{
if (!stream || !stream->s_ops || !stream->s_ops->s_seek) {
return B_ERR_NOT_SUPPORTED;
}
return stream->s_ops->s_seek(stream->s_obj, offset, origin);
}
static enum b_status stream_reserve(struct stream_data *stream, size_t len)
{
if (!stream || !stream->s_ops || !stream->s_ops->s_reserve) {
return B_ERR_NOT_SUPPORTED;
}
return stream->s_ops->s_reserve(stream->s_obj, len);
}
static enum b_status stream_read_char(struct stream_data *stream, int *c)
{
if (!(stream->s_cfg->s_mode & B_STREAM_READ)) {
return B_ERR_NOT_SUPPORTED;
}
enum b_status status = B_ERR_NOT_SUPPORTED;
if (stream->s_ops->s_getc) {
status = stream->s_ops->s_getc(stream->s_obj, c);
} else if (stream->s_ops->s_read) {
size_t r;
unsigned char v = 0;
status = stream->s_ops->s_read(stream->s_obj, &v, 1, &r);
*c = v;
if (status == B_SUCCESS && r < 1) {
status = B_ERR_NO_DATA;
}
}
return status;
}
static enum b_status __write_char(struct stream_data *stream, char c)
{
size_t w;
enum b_status status = stream->s_ops->s_write(
stream->s_obj, (unsigned char *)&c, 1, &w);
if (status == B_SUCCESS && w < 1) {
status = B_ERR_IO_FAILURE;
}
return status;
}
static enum b_status stream_write_char(struct stream_data *stream, char c)
{
if (!(stream->s_cfg->s_mode & B_STREAM_WRITE)) {
return B_ERR_NOT_SUPPORTED;
}
enum b_status status = B_ERR_NOT_SUPPORTED;
if (!stream->s_ops->s_write) {
return B_ERR_NOT_SUPPORTED;
}
if (c == '\n') {
stream->s_private->s_add_indent = 1;
}
if (!stream->s_private->s_istack_size) {
return __write_char(stream, c);
}
if (stream->s_private->s_add_indent && c != '\n') {
int indent = current_indent(stream);
for (int i = 0; i < indent; i++) {
__write_char(stream, ' ');
__write_char(stream, ' ');
}
stream->s_private->s_add_indent = 0;
}
__write_char(stream, c);
if (c == '\n') {
stream->s_private->s_add_indent = 1;
}
return B_SUCCESS;
}
static enum b_status stream_read_bytes(
struct stream_data *stream, void *buf, size_t count, size_t *nr_read)
{
if (!(stream->s_cfg->s_mode & B_STREAM_READ)) {
return B_ERR_NOT_SUPPORTED;
}
enum b_status status = B_ERR_NOT_SUPPORTED;
if (!stream->s_ops->s_read) {
return status;
}
return stream->s_ops->s_read(stream->s_obj, buf, count, nr_read);
}
static enum b_status stream_read_line(struct stream_data *stream, char *s, size_t max)
{
if (!(stream->s_cfg->s_mode & B_STREAM_READ)) {
return B_ERR_NOT_SUPPORTED;
}
enum b_status status = B_SUCCESS;
size_t i = 0;
int c = 0;
while (1) {
if (i >= max) {
break;
}
status = stream_read_char(stream, &c);
if (status != B_SUCCESS) {
break;
}
if (c == '\n') {
break;
}
s[i++] = c;
s[i] = '\0';
}
return B_SUCCESS;
}
static enum b_status stream_read_line_s(
struct stream_data *src, struct stream_data *dest)
{
if (!(src->s_cfg->s_mode & B_STREAM_READ)) {
return B_ERR_NOT_SUPPORTED;
}
if (!(dest->s_cfg->s_mode & B_STREAM_WRITE)) {
return B_ERR_NOT_SUPPORTED;
}
enum b_status status = B_SUCCESS;
size_t i = 0;
int c = 0;
while (1) {
status = stream_read_char(src, &c);
if (status != B_SUCCESS) {
break;
}
stream_write_char(dest, c);
i++;
if (c == '\n') {
break;
}
}
if (status == B_ERR_NO_DATA && i > 0) {
status = B_SUCCESS;
}
return status;
}
static enum b_status stream_write_bytes(
struct stream_data *stream, const void *buf, size_t count, size_t *nr_written)
{
if (!(stream->s_cfg->s_mode & B_STREAM_WRITE)) {
return B_ERR_NOT_SUPPORTED;
}
enum b_status status = B_ERR_NOT_SUPPORTED;
if (!stream->s_ops->s_write) {
return status;
}
return stream->s_ops->s_write(stream->s_obj, buf, count, nr_written);
}
static enum b_status stream_read_all_bytes(
struct stream_data *stream, void *p, size_t max, size_t *out_nr_read)
{
if (!(stream->s_cfg->s_mode & B_STREAM_READ)) {
return B_ERR_NOT_SUPPORTED;
}
enum b_status status = B_SUCCESS;
size_t nr_read = 0;
unsigned char *s = p;
while (nr_read < max) {
int c;
status = stream_read_char(stream, &c);
if (status != B_SUCCESS) {
break;
}
s[nr_read++] = c;
}
if (status == B_ERR_NO_DATA && nr_read > 0) {
status = B_SUCCESS;
}
*out_nr_read = nr_read;
return status;
}
static enum b_status stream_read_all_bytes_s(
struct stream_data *src, struct stream_data *dest,
struct b_stream_buffer_p *buffer, size_t *out_nr_read)
{
if (!(src->s_cfg->s_mode & B_STREAM_READ)) {
return B_ERR_NOT_SUPPORTED;
}
if (!(dest->s_cfg->s_mode & B_STREAM_WRITE)) {
return B_ERR_NOT_SUPPORTED;
}
if (!buffer) {
return B_ERR_INVALID_ARGUMENT;
}
if (src->s_ops->s_seek && dest->s_ops->s_reserve) {
size_t offset = stream_cursor(src);
stream_seek(src, 0, B_STREAM_SEEK_END);
size_t length = stream_cursor(src);
stream_seek(src, offset, B_STREAM_SEEK_START);
stream_reserve(dest, length);
}
enum b_status status = B_SUCCESS;
size_t nr_read = 0;
while (1) {
size_t r = 0, w = 0;
status = stream_read_bytes(
src, buffer->p_buf, buffer->p_buf_len, &r);
if (status != B_SUCCESS) {
break;
}
status = stream_write_bytes(dest, buffer->p_buf, r, &w);
nr_read += w;
if (status != B_SUCCESS || w != buffer->p_buf_len) {
break;
}
}
if (status == B_ERR_NO_DATA && nr_read > 0) {
status = B_SUCCESS;
}
if (out_nr_read) {
*out_nr_read = nr_read;
}
return status;
}
static enum b_status stream_write_string(
struct stream_data *stream, const char *s, size_t *nr_written)
{
size_t i;
enum b_status status = B_SUCCESS;
for (i = 0; s[i]; i++) {
status = stream_write_char(stream, s[i]);
if (!B_OK(status)) {
break;
}
}
if (nr_written) {
*nr_written = i;
}
return status;
}
static b_stream *init_stdio_stream(FILE *fp, b_stream_mode mode)
{
b_stdio_stream *stream = b_object_create(B_TYPE_STDIO_STREAM);
if (!stream) {
return NULL;
}
struct b_stdio_stream_p *p
= b_object_get_private(stream, B_TYPE_STDIO_STREAM);
b_stream_cfg *cfg = b_object_get_protected(stream, B_TYPE_STREAM);
p->s_fp = fp;
cfg->s_mode = mode;
return stream;
}
static enum b_status stream_push_indent(struct stream_data *stream, int indent)
{
if (!(stream->s_cfg->s_mode & B_STREAM_WRITE)) {
return B_ERR_NOT_SUPPORTED;
}
if (stream->s_cfg->s_mode & B_STREAM_BINARY) {
return B_ERR_NOT_SUPPORTED;
}
if (!stream->s_private->s_istack) {
stream->s_private->s_istack = calloc(4, sizeof(int));
stream->s_private->s_istack_size = 4;
stream->s_private->s_istack_ptr = 0;
}
if (stream->s_private->s_istack_ptr + 1 >= stream->s_private->s_istack_size) {
int *buf = realloc(
stream->s_private->s_istack,
(stream->s_private->s_istack_size + 4) * sizeof(int));
if (!buf) {
return B_ERR_NO_MEMORY;
}
stream->s_private->s_istack = buf;
stream->s_private->s_istack_size += 4;
}
int cur_indent
= stream->s_private->s_istack[stream->s_private->s_istack_ptr];
stream->s_private->s_istack[++stream->s_private->s_istack_ptr]
= cur_indent + indent;
return B_SUCCESS;
}
static enum b_status stream_pop_indent(struct stream_data *stream)
{
if (!(stream->s_cfg->s_mode & B_STREAM_WRITE)) {
return B_ERR_NOT_SUPPORTED;
}
if (stream->s_cfg->s_mode & B_STREAM_BINARY) {
return B_ERR_NOT_SUPPORTED;
}
if (!stream->s_private->s_istack || !stream->s_private->s_istack_size
|| !stream->s_private->s_istack_ptr) {
return B_SUCCESS;
}
stream->s_private->s_istack_ptr--;
return B_SUCCESS;
}
static void fctprintf_callback(char c, void *p)
{
struct stream_data *stream = p;
stream_write_char(stream, c);
}
/*** PUBLIC FUNCTIONS *********************************************************/
b_stream *z__b_stream_get_stdin(void)
{
if (!stdio[IDX_STDIN]) {
stdio[IDX_STDIN] = init_stdio_stream(stdin, B_STREAM_READ);
}
return stdio[IDX_STDIN];
}
b_stream *z__b_stream_get_stdout(void)
{
if (!stdio[IDX_STDOUT]) {
stdio[IDX_STDOUT] = init_stdio_stream(stdout, B_STREAM_WRITE);
}
return stdio[IDX_STDOUT];
}
b_stream *z__b_stream_get_stderr(void)
{
if (!stdio[IDX_STDERR]) {
stdio[IDX_STDERR] = init_stdio_stream(stderr, B_STREAM_WRITE);
}
return stdio[IDX_STDERR];
}
b_stream_buffer *b_stream_buffer_create_dynamic(size_t buffer_size)
{
b_stream_buffer *buffer = b_object_create(B_TYPE_STREAM_BUFFER);
if (!buffer) {
return NULL;
}
struct b_stream_buffer_p *p
= b_object_get_private(buffer, B_TYPE_STREAM_BUFFER);
p->p_buf = malloc(buffer_size);
if (!p->p_buf) {
b_stream_buffer_unref(buffer);
return NULL;
}
p->p_buf_len = buffer_size;
p->p_flags = B_STREAM_BUFFER_F_DYNAMIC;
return buffer;
}
b_stream_buffer *b_stream_buffer_create(void *buf, size_t len)
{
b_stream_buffer *buffer = b_object_create(B_TYPE_STREAM_BUFFER);
if (!buffer) {
return NULL;
}
struct b_stream_buffer_p *p
= b_object_get_private(buffer, B_TYPE_STREAM_BUFFER);
p->p_buf = buf;
p->p_buf_len = len;
p->p_flags = 0;
return buffer;
}
b_stream *b_stream_open_fp(FILE *fp)
{
b_stream *stream = b_object_create(B_TYPE_STREAM);
if (!stream) {
return NULL;
}
struct stream_data p;
stream_get_data(stream, &p);
p.s_cfg->s_mode = B_STREAM_READ | B_STREAM_WRITE;
p.s_private->s_ptr0 = fp;
p.s_ops->s_read = stdio_read;
p.s_ops->s_write = stdio_write;
p.s_ops->s_seek = stdio_seek;
p.s_ops->s_tell = stdio_tell;
return stream;
}
enum b_status b_stream_reserve(b_stream *stream, size_t len)
{
B_CLASS_DISPATCH_VIRTUAL(
b_stream, B_TYPE_STREAM, B_ERR_NOT_SUPPORTED, s_reserve, stream,
len);
}
enum b_status b_stream_seek(
b_stream *stream, long long offset, b_stream_seek_origin origin)
{
B_CLASS_DISPATCH_VIRTUAL(
b_stream, B_TYPE_STREAM, B_ERR_NOT_SUPPORTED, s_seek, stream,
offset, origin);
}
size_t b_stream_cursor(const b_stream *stream)
{
STREAM_DISPATCH_VIRTUAL_0(stream_cursor, stream);
}
enum b_status b_stream_push_indent(b_stream *strp, int indent)
{
STREAM_DISPATCH_VIRTUAL(stream_push_indent, strp, indent);
}
enum b_status b_stream_pop_indent(b_stream *strp)
{
STREAM_DISPATCH_VIRTUAL_0(stream_pop_indent, strp);
}
enum b_status b_stream_read_char(b_stream *strp, int *c)
{
STREAM_DISPATCH_VIRTUAL(stream_read_char, strp, c);
}
enum b_status b_stream_read_bytes(
b_stream *strp, void *buf, size_t count, size_t *nr_read)
{
STREAM_DISPATCH_VIRTUAL(stream_read_bytes, strp, buf, count, nr_read);
}
enum b_status b_stream_read_line(b_stream *strp, char *s, size_t max)
{
STREAM_DISPATCH_VIRTUAL(stream_read_line, strp, s, max);
}
enum b_status b_stream_read_line_s(b_stream *src, b_stream *dest)
{
enum b_status status;
struct stream_data src_p, dest_p;
status = stream_get_data(src, &src_p);
if (!B_OK(status)) {
return status;
}
status = stream_get_data(dest, &dest_p);
if (!B_OK(status)) {
return status;
}
return stream_read_line_s(&src_p, &dest_p);
}
enum b_status b_stream_read_all_bytes(
b_stream *stream, void *p, size_t max, size_t *out_nr_read)
{
STREAM_DISPATCH_VIRTUAL(stream_read_all_bytes, stream, p, max, out_nr_read);
}
enum b_status b_stream_read_all_bytes_s(
b_stream *src, b_stream *dest, b_stream_buffer *buffer, size_t *out_nr_read)
{
enum b_status status;
struct stream_data src_p, dest_p;
struct b_stream_buffer_p *buffer_p;
status = stream_get_data(src, &src_p);
if (!B_OK(status)) {
return status;
}
status = stream_get_data(dest, &dest_p);
if (!B_OK(status)) {
return status;
}
buffer_p = b_object_get_private(buffer, B_TYPE_STREAM_BUFFER);
if (!buffer_p) {
return B_ERR_INVALID_ARGUMENT;
}
return stream_read_all_bytes_s(&src_p, &dest_p, buffer_p, out_nr_read);
}
enum b_status b_stream_write_char(b_stream *stream, char c)
{
STREAM_DISPATCH_VIRTUAL(stream_write_char, stream, c);
}
enum b_status b_stream_write_string(
b_stream *stream, const char *s, size_t *nr_written)
{
STREAM_DISPATCH_VIRTUAL(stream_write_string, stream, s, nr_written);
}
enum b_status b_stream_write_bytes(
b_stream *stream, const void *buf, size_t count, size_t *nr_written)
{
STREAM_DISPATCH_VIRTUAL(stream_write_bytes, stream, buf, count, nr_written);
}
enum b_status b_stream_write_fmt(
b_stream *stream, size_t *nr_written, const char *format, ...)
{
struct stream_data p;
enum b_status status = stream_get_data(stream, &p);
va_list arg;
va_start(arg, format);
int w = z__b_fctprintf(fctprintf_callback, &p, format, arg);
va_end(arg);
if (nr_written) {
*nr_written = w;
}
return B_SUCCESS;
}
enum b_status b_stream_write_vfmt(
b_stream *stream, size_t *nr_written, const char *format, va_list arg)
{
struct stream_data p;
enum b_status status = stream_get_data(stream, &p);
int w = z__b_fctprintf(fctprintf_callback, &p, format, arg);
if (nr_written) {
*nr_written = w;
}
return B_SUCCESS;
}
/*** VIRTUAL FUNCTIONS ********************************************************/
static void stream_init(b_object *obj, void *priv)
{
struct b_stream_p *stream = priv;
}
static void stream_fini(b_object *obj, void *priv)
{
struct b_stream_p *stream = priv;
b_stream_class *ops = b_object_get_interface(obj, B_TYPE_STREAM);
if (stream->s_istack) {
free(stream->s_istack);
}
if (ops->s_close) {
ops->s_close(obj);
}
}
static void stream_buffer_init(b_object *obj, void *priv)
{
struct b_stream_buffer_p *buffer = priv;
}
static void stream_buffer_fini(b_object *obj, void *priv)
{
struct b_stream_buffer_p *buffer = priv;
if (buffer->p_flags & B_STREAM_BUFFER_F_DYNAMIC) {
free(buffer->p_buf);
}
}
static void stdio_stream_init(b_object *obj, void *priv)
{
struct b_stdio_stream_p *stream = priv;
}
static void stdio_stream_fini(b_object *obj, void *priv)
{
struct b_stdio_stream_p *stream = priv;
}
static enum b_status stdio_read(
b_stream *stream, unsigned char *out, size_t max, size_t *nr_read)
{
struct b_stdio_stream_p *p
= b_object_get_private(stream, B_TYPE_STDIO_STREAM);
enum b_status status = B_SUCCESS;
size_t count = fread(out, 1, max, p->s_fp);
if (ferror(p->s_fp)) {
status = B_ERR_IO_FAILURE;
}
*nr_read = count;
return status;
}
static enum b_status stdio_write(
b_stream *stream, const unsigned char *data, size_t count, size_t *nr_written)
{
struct b_stdio_stream_p *p
= b_object_get_private(stream, B_TYPE_STDIO_STREAM);
enum b_status status = B_SUCCESS;
size_t w = fwrite(data, 1, count, p->s_fp);
if (ferror(p->s_fp)) {
status = B_ERR_IO_FAILURE;
}
*nr_written = w;
return status;
}
static enum b_status stdio_seek(
b_stream *stream, long long offset, b_stream_seek_origin origin)
{
struct b_stdio_stream_p *p
= b_object_get_private(stream, B_TYPE_STDIO_STREAM);
int whence = 0;
switch (origin) {
case B_STREAM_SEEK_START:
whence = SEEK_SET;
break;
case B_STREAM_SEEK_CURRENT:
whence = SEEK_CUR;
break;
case B_STREAM_SEEK_END:
whence = SEEK_END;
break;
default:
return B_ERR_INVALID_ARGUMENT;
}
int ret = fseek(p->s_fp, offset, whence);
if (ret != 0) {
return B_ERR_NOT_SUPPORTED;
}
return B_SUCCESS;
}
static enum b_status stdio_tell(const b_stream *stream, size_t *cursor)
{
struct b_stdio_stream_p *p
= b_object_get_private(stream, B_TYPE_STDIO_STREAM);
long pos = ftell(p->s_fp);
if (pos == -1L) {
return B_ERR_NOT_SUPPORTED;
}
*cursor = (size_t)pos;
return B_SUCCESS;
}
/*** CLASS DEFINITION *********************************************************/
// ---- b_stream DEFINITION
B_TYPE_CLASS_DEFINITION_BEGIN(b_stream)
B_TYPE_CLASS_INTERFACE_BEGIN(b_object, B_TYPE_OBJECT)
B_INTERFACE_ENTRY(to_string) = NULL;
B_TYPE_CLASS_INTERFACE_END(b_object, B_TYPE_OBJECT)
B_TYPE_CLASS_DEFINITION_END(b_stream)
B_TYPE_DEFINITION_BEGIN(b_stream)
B_TYPE_ID(0xa2c98988, 0x30e5, 0x47c7, 0x88cd, 0x6c8ea79f69cd);
B_TYPE_CLASS(b_stream_class);
B_TYPE_INSTANCE_PRIVATE(struct b_stream_p);
B_TYPE_INSTANCE_PROTECTED(b_stream_cfg);
B_TYPE_INSTANCE_INIT(stream_init);
B_TYPE_INSTANCE_FINI(stream_fini);
B_TYPE_DEFINITION_END(b_stream)
// ---- b_stream_buffer DEFINITION
B_TYPE_CLASS_DEFINITION_BEGIN(b_stream_buffer)
B_TYPE_CLASS_INTERFACE_BEGIN(b_object, B_TYPE_OBJECT)
B_INTERFACE_ENTRY(to_string) = NULL;
B_TYPE_CLASS_INTERFACE_END(b_object, B_TYPE_OBJECT)
B_TYPE_CLASS_DEFINITION_END(b_stream_buffer)
B_TYPE_DEFINITION_BEGIN(b_stream_buffer)
B_TYPE_ID(0x575c7be1, 0x665f, 0x41f8, 0xbfed, 0x6269a2985be0);
B_TYPE_CLASS(b_stream_buffer_class);
B_TYPE_INSTANCE_PRIVATE(struct b_stream_buffer_p);
B_TYPE_INSTANCE_INIT(stream_buffer_init);
B_TYPE_INSTANCE_FINI(stream_buffer_fini);
B_TYPE_DEFINITION_END(b_stream_buffer)
// ---- b_stdio_stream DEFINITION
B_TYPE_CLASS_DEFINITION_BEGIN(b_stdio_stream)
B_TYPE_CLASS_INTERFACE_BEGIN(b_object, B_TYPE_OBJECT)
B_INTERFACE_ENTRY(to_string) = NULL;
B_TYPE_CLASS_INTERFACE_END(b_object, B_TYPE_OBJECT)
B_TYPE_CLASS_INTERFACE_BEGIN(b_stream, B_TYPE_STREAM)
B_INTERFACE_ENTRY(s_close) = NULL;
B_INTERFACE_ENTRY(s_seek) = stdio_seek;
B_INTERFACE_ENTRY(s_tell) = stdio_tell;
B_INTERFACE_ENTRY(s_getc) = NULL;
B_INTERFACE_ENTRY(s_read) = stdio_read;
B_INTERFACE_ENTRY(s_write) = stdio_write;
B_INTERFACE_ENTRY(s_reserve) = NULL;
B_TYPE_CLASS_INTERFACE_END(b_stream, B_TYPE_STREAM)
B_TYPE_CLASS_DEFINITION_END(b_stdio_stream)
B_TYPE_DEFINITION_BEGIN(b_stdio_stream)
B_TYPE_ID(0x67678926, 0xd0b7, 0x4f99, 0xb83c, 0x790927597645);
B_TYPE_EXTENDS(B_TYPE_STREAM);
B_TYPE_CLASS(b_stdio_stream_class);
B_TYPE_INSTANCE_PRIVATE(struct b_stdio_stream_p);
B_TYPE_INSTANCE_INIT(stdio_stream_init);
B_TYPE_INSTANCE_FINI(stdio_stream_fini);
B_TYPE_DEFINITION_END(b_stdio_stream)