#include "posix.h" #include #include #include #include #include #include #include /*** PRIVATE DATA *************************************************************/ struct fx_iostream_p { int s_fd; bool s_fd_close_on_release; }; /*** PRIVATE FUNCTIONS ********************************************************/ static uptr iostream_get_os_handle(const struct fx_iostream_p *stream) { return stream->s_fd; } static uptr iostream_steal_os_handle(struct fx_iostream_p *stream) { uptr out = stream->s_fd; stream->s_fd = -1; stream->s_fd_close_on_release = false; return out; } /*** PUBLIC FUNCTIONS *********************************************************/ fx_iostream *fx_iostream_create( fx_stream_mode mode, uptr os_handle, bool close_handle_on_release) { fx_iostream *s = fx_object_create(FX_IO_TYPE_STREAM); if (!s) { return NULL; } fx_stream_cfg *cfg = fx_object_get_protected(s, FX_TYPE_STREAM); struct fx_iostream_p *p = fx_object_get_private(s, FX_IO_TYPE_STREAM); cfg->s_mode = mode | Z__FX_STREAM_STATIC; p->s_fd = (int)os_handle; p->s_fd_close_on_release = close_handle_on_release; return s; } uptr fx_iostream_get_os_handle(const fx_iostream *stream) { FX_CLASS_DISPATCH_STATIC_0( FX_IO_TYPE_STREAM, iostream_get_os_handle, stream); } uptr fx_iostream_steal_os_handle(fx_iostream *stream) { FX_CLASS_DISPATCH_STATIC_0( FX_IO_TYPE_STREAM, iostream_steal_os_handle, stream); } /*** VIRTUAL FUNCTIONS ********************************************************/ static void iostream_init(fx_object *obj, void *priv) { struct fx_iostream_p *stream = priv; } static void iostream_fini(fx_object *obj, void *priv) { struct fx_iostream_p *stream = priv; if (stream->s_fd_close_on_release) { close(stream->s_fd); } } static enum fx_status stream_read( fx_stream *stream, void *buf, size_t count, size_t *nr_read) { struct fx_iostream_p *s = fx_object_get_private(stream, FX_IO_TYPE_STREAM); long r = read(s->s_fd, buf, count); if (r < 0) { return fx_status_from_errno(errno, FX_ERR_IO_FAILURE); } *nr_read = r; return FX_SUCCESS; } static enum fx_status stream_write( fx_stream *stream, const void *buf, size_t count, size_t *nr_written) { struct fx_iostream_p *s = fx_object_get_private(stream, FX_IO_TYPE_STREAM); long w = write(s->s_fd, buf, count); if (w < 0) { return fx_status_from_errno(errno, FX_ERR_IO_FAILURE); } *nr_written = w; return FX_SUCCESS; } /*** CLASS DEFINITION *********************************************************/ FX_TYPE_CLASS_BEGIN(fx_iostream) FX_TYPE_VTABLE_INTERFACE_BEGIN(fx_object, FX_TYPE_OBJECT) FX_INTERFACE_ENTRY(to_string) = NULL; FX_TYPE_VTABLE_INTERFACE_END(fx_object, FX_TYPE_OBJECT) FX_TYPE_VTABLE_INTERFACE_BEGIN(fx_stream, FX_TYPE_STREAM) FX_INTERFACE_ENTRY(s_close) = NULL; FX_INTERFACE_ENTRY(s_seek) = NULL; FX_INTERFACE_ENTRY(s_tell) = NULL; FX_INTERFACE_ENTRY(s_getc) = NULL; FX_INTERFACE_ENTRY(s_read) = stream_read; FX_INTERFACE_ENTRY(s_write) = stream_write; FX_INTERFACE_ENTRY(s_reserve) = NULL; FX_TYPE_VTABLE_INTERFACE_END(fx_stream, FX_TYPE_STREAM) FX_TYPE_CLASS_END(fx_iostream) FX_TYPE_DEFINITION_BEGIN(fx_iostream) FX_TYPE_ID(0xc0b1c3c9, 0xa9c6, 0x4910, 0x8786, 0x574b0696e7aa); FX_TYPE_NAME("fx.io.stream"); FX_TYPE_EXTENDS(FX_TYPE_STREAM); FX_TYPE_CLASS(fx_iostream_class); FX_TYPE_INSTANCE_PRIVATE(struct fx_iostream_p); FX_TYPE_INSTANCE_INIT(iostream_init); FX_TYPE_INSTANCE_FINI(iostream_fini); FX_TYPE_DEFINITION_END(fx_iostream)