From 9ea70191909f6497f59e2a888c834e18bbbf9740 Mon Sep 17 00:00:00 2001 From: "hyunghwan.chung" Date: Wed, 23 Oct 2019 16:40:02 +0000 Subject: [PATCH] adding mod/io.c --- moo/kernel/Socket.moo | 32 ++--- moo/kernel/Stream.moo | 6 +- moo/mod/_io.h | 53 +++++++++ moo/mod/io.c | 266 ++++++++++++++++++++++++++++++++++++++++++ moo/mod/sck.c | 4 +- 5 files changed, 340 insertions(+), 21 deletions(-) create mode 100644 moo/mod/_io.h create mode 100644 moo/mod/io.c diff --git a/moo/kernel/Socket.moo b/moo/kernel/Socket.moo index 167ca7f..9642295 100644 --- a/moo/kernel/Socket.moo +++ b/moo/kernel/Socket.moo @@ -30,7 +30,7 @@ class(#byte(4)) IP4Address(IPAddress) ^self new fromString: str. } - method __fromString: str offset: string_offset offset: address_offset + method __fromString: str startingAt: string_offset into: address_offset { | dots digits pos size c acc | @@ -84,7 +84,7 @@ class(#byte(4)) IP4Address(IPAddress) method fromString: str { - if ((self __fromString: str offset: 0 offset: 0) isError) + if ((self __fromString: str startingAt: 0 into: 0) isError) { Exception signal: ('invalid IPv4 address ' & str). } @@ -169,8 +169,8 @@ class(#byte(16)) IP6Address(IP4Address) if ((ch == $.) and (tgpos + 4 <= mysize)) { - //if ((super __fromString: (str copyFrom: curseg) offset:0 offset: tgpos) isError) { ^Error.Code.EINVAL }. - if ((super __fromString: str offset: curseg offset: tgpos) isError) { ^Error.Code.EINVAL }. + //if ((super __fromString: (str copyFrom: curseg) startingAt: 0 into: tgpos) isError) { ^Error.Code.EINVAL }. + if ((super __fromString: str startingAt: curseg into: tgpos) isError) { ^Error.Code.EINVAL }. tgpos := tgpos + 4. saw_xdigit := false. break. @@ -256,9 +256,9 @@ class Socket(Object) from 'sck' method(#primitive) _socketError. method(#primitive) _readBytesInto: bytes. - method(#primitive) _readBytesInto: bytes offset: offset length: length. + method(#primitive) _readBytesInto: bytes startingAt: offset for: length. method(#primitive) _writeBytesFrom: bytes. - method(#primitive) _writeBytesFrom: bytes offset: offset length: length. + method(#primitive) _writeBytesFrom: bytes startingAt: offset for: length. method(#class) new { self messageProhibited: #new } method(#class) new: size { self messageProhibited: #new: } @@ -398,12 +398,12 @@ class SyncSocket(Socket) } } - method readBytesInto: bytes offset: offset length: length + method readBytesInto: bytes startingAt: offset for: length { | n | while (true) { - n := super _readBytesInto: bytes offset: offset length: length. + n := super _readBytesInto: bytes startingAt: offset for: length. if (n >= 0) { ^n }. self __wait_for_input. } @@ -420,12 +420,12 @@ class SyncSocket(Socket) } } - method writeBytesFrom: bytes offset: offset length: length + method writeBytesFrom: bytes startingAt: offset for: length { | n | while (true) { - n := super _writeBytesFrom: bytes offset: offset length: length. + n := super _writeBytesFrom: bytes startingAt: offset for: length. if (n >= 0) { ^n }. self __wait_for_output. } @@ -468,7 +468,7 @@ class AsyncSocket(Socket) while (rem > 0) { - nbytes := self _writeBytesFrom: self.pending_bytes offset: pos length: rem. + nbytes := self _writeBytesFrom: self.pending_bytes startingAt: pos for: rem. if (nbytes <= -1) { break }. pos := pos + nbytes. rem := rem - nbytes. @@ -535,12 +535,12 @@ class AsyncSocket(Socket) ^super _readBytesInto: bytes. } - method readBytesInto: bytes offset: offset length: length + method readBytesInto: bytes startingAt: offset for: length { - ^super _readBytesInto: bytes offset: offset length: length. + ^super _readBytesInto: bytes startingAt: offset for: length. } - method writeBytesFrom: bytes offset: offset length: length + method writeBytesFrom: bytes startingAt: offset for: length { | n pos rem | @@ -558,7 +558,7 @@ class AsyncSocket(Socket) while (rem > 0) { - n := self _writeBytesFrom: bytes offset: pos length: rem. + n := self _writeBytesFrom: bytes startingAt: pos for: rem. if (n <= -1) { break }. rem := rem - n. pos := pos + n. @@ -580,7 +580,7 @@ class AsyncSocket(Socket) method writeBytesFrom: bytes { - ^self writeBytesFrom: bytes offset: 0 length: (bytes size) + ^self writeBytesFrom: bytes startingAt: 0 for: (bytes size) } //method onSocketClosed diff --git a/moo/kernel/Stream.moo b/moo/kernel/Stream.moo index e51fb31..819860b 100644 --- a/moo/kernel/Stream.moo +++ b/moo/kernel/Stream.moo @@ -233,7 +233,7 @@ class ByteStreamAdapter(Object) //# [ByteStreamable, ByteXXX] // don't rely on the internal buffer if the number of bytes // needed are equal to or greater than the capacity of the // buffer. - v := self.bsobj readBytesInto: byte_array offset: pos length: needed. + v := self.bsobj readBytesInto: byte_array at: pos for: needed. if (v isError or v <= 0) { break }. // <<< TODO: change the error handling pos := pos + v. needed := needed - v. @@ -275,7 +275,7 @@ class ByteStreamAdapter(Object) //# [ByteStreamable, ByteXXX] if (self.outlen <= 0 and rem >= outcapa) { - consumed := self.bsobj writeBytesFrom: byte_array offset: pos length: rem. + consumed := self.bsobj writeBytesFrom: byte_array at: pos for: rem. if (consumed <= 0) { break }. // TODO: error handling. also handle exceptions } else @@ -299,7 +299,7 @@ class ByteStreamAdapter(Object) //# [ByteStreamable, ByteXXX] pos := 0. while (pos < self.outlen) { - v := self.bsobj writeBytesFrom: self.outbuf offset: pos length: (self.outlen - pos). + v := self.bsobj writeBytesFrom: self.outbuf at: pos for: (self.outlen - pos). if (v <= 0) { break }. // TODO: error handling. also handle exceptions pos := pos + v. }. diff --git a/moo/mod/_io.h b/moo/mod/_io.h new file mode 100644 index 0000000..c7662b1 --- /dev/null +++ b/moo/mod/_io.h @@ -0,0 +1,53 @@ +/* + * $Id$ + * + Copyright (c) 2014-2018 Chung, Hyung-Hwan. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MOO_MOD_IO_H_ +#define _MOO_MOD_IO_H_ + +#include + +typedef struct io_t* oop_io_t; +struct io_t +{ + MOO_OBJ_HEADER; + moo_oop_t handle; /* SmallInteger */ + /* there are more fields in the actual object */ +}; + +#if defined(__cplusplus) +extern "C" { +#endif + +MOO_EXPORT int moo_mod_io (moo_t* moo, moo_mod_t* mod); +/*MOO_EXPORT int moo_mod_io_file (moo_t* moo, moo_mod_t* mod);*/ + + +#if defined(__cplusplus) +} +#endif + + +#endif diff --git a/moo/mod/io.c b/moo/mod/io.c new file mode 100644 index 0000000..0287db5 --- /dev/null +++ b/moo/mod/io.c @@ -0,0 +1,266 @@ +/* + * $Id$ + * + Copyright (c) 2014-2018 Chung, Hyung-Hwan. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "_io.h" + +#include +#include +#include +#include + +typedef struct io_modctx_t io_modctx_t; +struct io_modctx_t +{ + moo_oop_class_t io_class; +}; + +static moo_pfrc_t pf_close_io (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs) +{ + oop_io_t io; + int fd; + + io = (oop_io_t)MOO_STACK_GETRCV(moo, nargs); + MOO_PF_CHECK_RCV (moo, + MOO_OOP_IS_POINTER(io) && + MOO_OBJ_BYTESOF(io) >= (MOO_SIZEOF(*io) - MOO_SIZEOF(moo_obj_t)) && + MOO_OOP_IS_SMOOI(io->handle) + ); + + fd = MOO_OOP_TO_SMOOI(io->handle); + if (fd >= 0) + { + moo_releaseiohandle (moo, MOO_OOP_TO_SMOOI(io->handle)); + if (close(MOO_OOP_TO_SMOOI(io->handle)) == -1) + { + moo_seterrwithsyserr (moo, 0, errno); + return MOO_PF_FAILURE; + } + else + { + io->handle = MOO_SMOOI_TO_OOP(-1); + MOO_STACK_SETRETTORCV (moo, nargs); + return MOO_PF_SUCCESS; + } + } + + moo_seterrbfmt (moo, MOO_EBADHND, "bad IO handle - %O", io->handle); + return MOO_PF_FAILURE; +} + +#if 0 +static moo_pfrc_t pf_read_io (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs) +{ + oop_io_t io; + moo_oop_byte_t buf; + moo_oow_t offset, length, maxlen; + int fd; + ssize_t n; + + io = (oop_io_t)MOO_STACK_GETRCV(moo, nargs); + MOO_PF_CHECK_RCV (moo, + MOO_OOP_IS_POINTER(io) && + MOO_OBJ_BYTESOF(io) >= (MOO_SIZEOF(*io) - MOO_SIZEOF(moo_obj_t)) && + MOO_OOP_IS_SMOOI(io->handle) + ); + + fd = MOO_OOP_TO_SMOOI(io->handle); + if (fd <= -1) + { + moo_seterrbfmt (moo, MOO_EINVAL, "bad socket handle - %d", fd); + return MOO_PF_FAILURE; + } + + buf = (moo_oop_byte_t)MOO_STACK_GETARG (moo, nargs, 0); + if (!MOO_OBJ_IS_BYTE_POINTER(buf)) + { + moo_seterrbfmt (moo, MOO_EINVAL, "buffer not a byte array - %O", buf); + return MOO_PF_FAILURE; + } + + offset = 0; + maxlen = MOO_OBJ_GET_SIZE(buf); + length = maxlen; + + if (nargs >= 2) + { + moo_oop_t tmp; + + tmp = MOO_STACK_GETARG(moo, nargs, 1); + if (moo_inttooow (moo, tmp, &offset) <= 0) + { + moo_seterrbfmt (moo, MOO_EINVAL, "invalid offset - %O", tmp); + return MOO_PF_FAILURE; + } + + if (nargs >= 3) + { + tmp = MOO_STACK_GETARG(moo, nargs, 2); + if (moo_inttooow(moo, tmp, &length) <= 0) + { + moo_seterrbfmt (moo, MOO_EINVAL, "invalid length - %O", tmp); + return MOO_PF_FAILURE; + } + } + + if (offset >= maxlen) offset = maxlen - 1; + if (length > maxlen - offset) length = maxlen - offset; + } + + n = recv(fd, MOO_OBJ_GET_BYTE_PTR(buf, offset), length, 0); + if (n <= -1 && errno != EWOULDBLOCK && errno != EAGAIN) + { + moo_seterrwithsyserr (moo, 0, errno); + return MOO_PF_FAILURE; + } + + /* [NOTE] on EWOULDBLOCK or EGAIN, -1 is returned */ + + MOO_ASSERT (moo, MOO_IN_SMOOI_RANGE(n)); + + MOO_STACK_SETRET (moo, nargs, MOO_SMOOI_TO_OOP(n)); + return MOO_PF_SUCCESS; +} + +static moo_pfrc_t pf_write_io (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs) +{ + oop_io_t io; + moo_oop_byte_t buf; + moo_oow_t offset, length, maxlen; + int fd; + ssize_t n; + + io = (oop_io_t)MOO_STACK_GETRCV(moo, nargs); + MOO_PF_CHECK_RCV (moo, + MOO_OOP_IS_POINTER(io) && + MOO_OBJ_BYTESOF(io) >= (MOO_SIZEOF(*io) - MOO_SIZEOF(moo_obj_t)) && + MOO_OOP_IS_SMOOI(io->handle) + ); + + fd = MOO_OOP_TO_SMOOI(io->handle); + if (fd <= -1) + { + moo_seterrbfmt (moo, MOO_EINVAL, "bad socket handle - %d", fd); + return MOO_PF_FAILURE; + } + + buf = (moo_oop_byte_t)MOO_STACK_GETARG (moo, nargs, 0); + if (!MOO_OBJ_IS_BYTE_POINTER(buf)) + { + moo_seterrbfmt (moo, MOO_EINVAL, "buffer not a byte array - %O", buf); + return MOO_PF_FAILURE; + } + + offset = 0; + maxlen = MOO_OBJ_GET_SIZE(buf); + length = maxlen; + + if (nargs >= 2) + { + moo_oop_t tmp; + + tmp = MOO_STACK_GETARG(moo, nargs, 1); + if (moo_inttooow (moo, tmp, &offset) <= 0) + { + moo_seterrbfmt (moo, MOO_EINVAL, "invalid offset - %O", tmp); + return MOO_PF_FAILURE; + } + + if (nargs >= 3) + { + tmp = MOO_STACK_GETARG(moo, nargs, 2); + if (moo_inttooow(moo, tmp, &length) <= 0) + { + moo_seterrbfmt (moo, MOO_EINVAL, "invalid length - %O", tmp); + return MOO_PF_FAILURE; + } + } + + if (offset >= maxlen) offset = maxlen - 1; + if (length > maxlen - offset) length = maxlen - offset; + } + + n = send(fd, MOO_OBJ_GET_BYTE_PTR(buf, offset), length, 0); + if (n <= -1 && errno != EWOULDBLOCK && errno != EAGAIN) + { + moo_seterrwithsyserr (moo, 0, errno); + return MOO_PF_FAILURE; + } + + /* [NOTE] on EWOULDBLOCK or EGAIN, -1 is returned */ + MOO_ASSERT (moo, MOO_IN_SMOOI_RANGE(n)); + + MOO_STACK_SETRET (moo, nargs, MOO_SMOOI_TO_OOP(n)); + return MOO_PF_SUCCESS; +} +#endif + +/* ------------------------------------------------------------------------ */ + +typedef struct fnctab_t fnctab_t; +struct fnctab_t +{ + moo_method_type_t type; + moo_ooch_t mthname[15]; + int variadic; + moo_pfimpl_t handler; +}; + +#define C MOO_METHOD_CLASS +#define I MOO_METHOD_INSTANCE + +#define MA MOO_TYPE_MAX(moo_oow_t) + +static moo_pfinfo_t pfinfos[] = +{ + { I, { 'c','l','o','s','e','\0' }, 0, { pf_close_io, 0, 0 } }, +}; + +/* ------------------------------------------------------------------------ */ + +static int import (moo_t* moo, moo_mod_t* mod, moo_oop_class_t _class) +{ + /*if (moo_setclasstrsize(moo, _class, MOO_SIZEOF(io_t), MOO_NULL) <= -1) return -1;*/ + return 0; +} + +static moo_pfbase_t* query (moo_t* moo, moo_mod_t* mod, const moo_ooch_t* name, moo_oow_t namelen) +{ + return moo_findpfbase(moo, pfinfos, MOO_COUNTOF(pfinfos), name, namelen); +} + +static void unload (moo_t* moo, moo_mod_t* mod) +{ + /* TODO: anything? close open open dll handles? For that, pf_open must store the value it returns to mod->ctx or somewhere..*/ + if (mod->ctx) moo_freemem (moo, mod->ctx); +} + +int moo_mod_io (moo_t* moo, moo_mod_t* mod) +{ + mod->import = import; + mod->query = query; + mod->unload = unload; + return 0; +} diff --git a/moo/mod/sck.c b/moo/mod/sck.c index ea59a42..314cab5 100644 --- a/moo/mod/sck.c +++ b/moo/mod/sck.c @@ -593,10 +593,10 @@ static moo_pfinfo_t pfinfos[] = { I, { 'l','i','s','t','e','n',':','\0' }, 0, { pf_listen_socket, 1, 1 } }, { I, { 'o','p','e','n','\0' }, 0, { pf_open_socket, 1, 3 } }, { I, { 'r','e','a','d','B','y','t','e','s','I','n','t','o',':','\0' }, 0, { pf_read_socket, 1, 1 } }, - { I, { 'r','e','a','d','B','y','t','e','s','I','n','t','o',':','o','f','f','s','e','t',':','l','e','n','g','t','h',':','\0' }, 0, { pf_read_socket, 3, 3 } }, + { I, { 'r','e','a','d','B','y','t','e','s','I','n','t','o',':','s','t','a','r','t','i','n','g','A','t',':','f','o','r',':','\0' }, 0, { pf_read_socket, 3, 3 } }, { I, { 's','o','c','k','e','t','E','r','r','o','r','\0' }, 0, { pf_get_socket_error, 0, 0 } }, { I, { 'w','r','i','t','e','B','y','t','e','s','F','r','o','m',':','\0' }, 0, { pf_write_socket, 1, 1 } }, - { I, { 'w','r','i','t','e','B','y','t','e','s','F','r','o','m',':','o','f','f','s','e','t',':','l','e','n','g','t','h',':','\0' }, 0, { pf_write_socket, 3, 3 } } + { I, { 'w','r','i','t','e','B','y','t','e','s','F','r','o','m',':','s','t','a','r','t','i','n','g','A','t',':','f','o','r',':','\0' }, 0, { pf_write_socket, 3, 3 } } }; /* ------------------------------------------------------------------------ */