adding mod/io.c

This commit is contained in:
hyunghwan.chung 2019-10-23 16:40:02 +00:00
parent dde40650c3
commit 9ea7019190
5 changed files with 340 additions and 21 deletions

View File

@ -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

View File

@ -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.
}.

53
moo/mod/_io.h Normal file
View File

@ -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 <moo.h>
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

266
moo/mod/io.c Normal file
View File

@ -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 <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
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;
}

View File

@ -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 } }
};
/* ------------------------------------------------------------------------ */