#include "printf.h" #include #include #include #include #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)