Skip to content

Commit

Permalink
Give each uv_handle type it's own metatable so method form can be used
Browse files Browse the repository at this point in the history
  • Loading branch information
creationix committed Dec 2, 2014
1 parent f373d2e commit 73964e9
Show file tree
Hide file tree
Showing 20 changed files with 273 additions and 32 deletions.
2 changes: 1 addition & 1 deletion src/async.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
#include "luv.h"

static uv_async_t* luv_check_async(lua_State* L, int index) {
uv_async_t* handle = luaL_checkudata(L, index, "uv_handle");
uv_async_t* handle = luaL_checkudata(L, index, "uv_async");
luaL_argcheck(L, handle->type == UV_ASYNC && handle->data, index, "Expected uv_async_t");
return handle;
}
Expand Down
2 changes: 1 addition & 1 deletion src/check.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
#include "luv.h"

static uv_check_t* luv_check_check(lua_State* L, int index) {
uv_check_t* handle = luaL_checkudata(L, index, "uv_handle");
uv_check_t* handle = luaL_checkudata(L, index, "uv_check");
luaL_argcheck(L, handle->type == UV_CHECK && handle->data, index, "Expected uv_check_t");
return handle;
}
Expand Down
2 changes: 1 addition & 1 deletion src/fs_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
#include "luv.h"

static uv_fs_event_t* luv_check_fs_event(lua_State* L, int index) {
uv_fs_event_t* handle = luaL_checkudata(L, index, "uv_handle");
uv_fs_event_t* handle = luaL_checkudata(L, index, "uv_fs_event");
luaL_argcheck(L, handle->type == UV_FS_EVENT && handle->data, index, "Expected uv_fs_event_t");
return handle;
}
Expand Down
2 changes: 1 addition & 1 deletion src/fs_poll.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
#include "luv.h"

static uv_fs_poll_t* luv_check_fs_poll(lua_State* L, int index) {
uv_fs_poll_t* handle = luaL_checkudata(L, index, "uv_handle");
uv_fs_poll_t* handle = luaL_checkudata(L, index, "uv_fs_poll");
luaL_argcheck(L, handle->type == UV_FS_POLL && handle->data, index, "Expected uv_fs_poll_t");
return handle;
}
Expand Down
22 changes: 12 additions & 10 deletions src/handle.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,23 @@
#include "luv.h"

static uv_handle_t* luv_check_handle(lua_State* L, int index) {
uv_handle_t* handle = luaL_checkudata(L, index, "uv_handle");
const uv_handle_t* handle;
luaL_checktype(L, index, LUA_TUSERDATA);
handle = lua_topointer(L, index);
luaL_argcheck(L, handle->data, index, "Expected uv_handle_t");
return handle;
switch (handle->type) {
#define XX(uc, lc) case(UV_##uc): return luaL_checkudata(L, index, "uv_"#lc);
UV_HANDLE_TYPE_MAP(XX)
#undef XX
default:
luaL_argerror(L, index, "Expected uv_handle_t");
return NULL;
}
}

// Show the libuv type instead of generic "userdata"
static int luv_handle_tostring(lua_State* L) {
uv_handle_t* handle = luaL_checkudata(L, 1, "uv_handle");
uv_handle_t* handle = luv_check_handle(L, 1);
switch (handle->type) {
#define XX(uc, lc) case UV_##uc: lua_pushfstring(L, "uv_"#lc"_t: %p", handle); break;
UV_HANDLE_TYPE_MAP(XX)
Expand All @@ -34,13 +43,6 @@ static int luv_handle_tostring(lua_State* L) {
return 1;
}

static void luv_handle_init(lua_State* L) {
luaL_newmetatable (L, "uv_handle");
lua_pushcfunction(L, luv_handle_tostring);
lua_setfield(L, -2, "__tostring");
lua_pop(L, 1);
}

static int luv_is_active(lua_State* L) {
uv_handle_t* handle = luv_check_handle(L, 1);
int ret = uv_is_active(handle);
Expand Down
2 changes: 1 addition & 1 deletion src/idle.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
#include "luv.h"

static uv_idle_t* luv_check_idle(lua_State* L, int index) {
uv_idle_t* handle = luaL_checkudata(L, index, "uv_handle");
uv_idle_t* handle = luaL_checkudata(L, index, "uv_idle");
luaL_argcheck(L, handle->type == UV_IDLE && handle->data, index, "Expected uv_idle_t");
return handle;
}
Expand Down
13 changes: 12 additions & 1 deletion src/lhandle.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,23 @@

static luv_handle_t* luv_setup_handle(lua_State* L) {
luv_handle_t* data;
const uv_handle_t* handle = lua_topointer(L, -1);
luaL_checktype(L, -1, LUA_TUSERDATA);

data = malloc(sizeof(*data));
if (!data) luaL_error(L, "Can't allocate luv handle");

luaL_getmetatable(L, "uv_handle");
#define XX(uc, lc) case UV_##uc: \
luaL_getmetatable(L, "uv_"#lc); \
break;
switch (handle->type) {
UV_HANDLE_TYPE_MAP(XX)
default:
luaL_error(L, "Unknown handle type");
return NULL;
}
#undef XX

lua_setmetatable(L, -2);

lua_pushvalue(L, -1);
Expand Down
167 changes: 167 additions & 0 deletions src/luv.c
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,173 @@ static const luaL_Reg luv_functions[] = {
{NULL, NULL}
};

static const luaL_Reg luv_handle_methods[] = {
// handle.c
{"is_active", luv_is_active},
{"is_closing", luv_is_closing},
{"close", luv_close},
{"ref", luv_ref},
{"unref", luv_unref},
{"has_ref", luv_has_ref},
{"send_buffer_size", luv_send_buffer_size},
{"recv_buffer_size", luv_recv_buffer_size},
{"fileno", luv_fileno},
};

static const luaL_Reg luv_async_methods[] = {
{"send", luv_async_send},
{NULL, NULL}
};

static const luaL_Reg luv_check_methods[] = {
{"start", luv_check_start},
{"stop", luv_check_stop},
{NULL, NULL}
};

static const luaL_Reg luv_fs_event_methods[] = {
{"start", luv_fs_event_start},
{"stop", luv_fs_event_stop},
{"getpath", luv_fs_event_getpath},
{NULL, NULL}
};

static const luaL_Reg luv_fs_poll_methods[] = {
{"start", luv_fs_poll_start},
{"stop", luv_fs_poll_stop},
{"getpath", luv_fs_poll_getpath},
{NULL, NULL}
};

static const luaL_Reg luv_idle_methods[] = {
{"start", luv_idle_start},
{"stop", luv_idle_stop},
{NULL, NULL}
};

static const luaL_Reg luv_stream_methods[] = {
{"shutdown", luv_shutdown},
{"listen", luv_listen},
{"accept", luv_accept},
{"read_start", luv_read_start},
{"read_stop", luv_read_stop},
{"write", luv_write},
{"write2", luv_write2},
{"try_write", luv_try_write},
{"is_readable", luv_is_readable},
{"is_writable", luv_is_writable},
{"set_blocking", luv_stream_set_blocking},
};

static const luaL_Reg luv_pipe_methods[] = {
{"open", luv_pipe_open},
{"bind", luv_pipe_bind},
{"connect", luv_pipe_connect},
{"getsockname", luv_pipe_getsockname},
{"pending_instances", luv_pipe_pending_instances},
{"pending_count", luv_pipe_pending_count},
{"pending_type", luv_pipe_pending_type},
{NULL, NULL}
};

static const luaL_Reg luv_poll_methods[] = {
{"start", luv_poll_start},
{"stop", luv_poll_stop},
{NULL, NULL}
};

static const luaL_Reg luv_prepare_methods[] = {
{"start", luv_prepare_start},
{"stop", luv_prepare_stop},
{NULL, NULL}
};

static const luaL_Reg luv_process_methods[] = {
{"kill", luv_process_kill},
{NULL, NULL}
};

static const luaL_Reg luv_tcp_methods[] = {
{"open", luv_tcp_open},
{"nodelay", luv_tcp_nodelay},
{"keepalive", luv_tcp_keepalive},
{"simultaneous_accepts", luv_tcp_simultaneous_accepts},
{"bind", luv_tcp_bind},
{"getpeername", luv_tcp_getpeername},
{"getsockname", luv_tcp_getsockname},
{"connect", luv_tcp_connect},
{"write_queue_size", luv_write_queue_size},
{NULL, NULL}
};

static const luaL_Reg luv_timer_methods[] = {
{"start", luv_timer_start},
{"stop", luv_timer_stop},
{"again", luv_timer_again},
{"set_repeat", luv_timer_set_repeat},
{"get_repeat", luv_timer_get_repeat},
{NULL, NULL}
};

static const luaL_Reg luv_tty_methods[] = {
{"set_mode", luv_tty_set_mode},
{"get_winsize", luv_tty_get_winsize},
{NULL, NULL}
};

static const luaL_Reg luv_udp_methods[] = {
{"open", luv_udp_open},
{"bind", luv_udp_bind},
{"bindgetsockname", luv_udp_getsockname},
{"set_membership", luv_udp_set_membership},
{"set_multicast_loop", luv_udp_set_multicast_loop},
{"set_multicast_ttl", luv_udp_set_multicast_ttl},
{"set_multicast_interface", luv_udp_set_multicast_interface},
{"set_broadcast", luv_udp_set_broadcast},
{"set_ttl", luv_udp_set_ttl},
{"send", luv_udp_send},
{"try_send", luv_udp_try_send},
{"recv_start", luv_udp_recv_start},
{"recv_stop", luv_udp_recv_stop},
{NULL, NULL}
};

static const luaL_Reg luv_signal_methods[] = {
{"start", luv_signal_start},
{"stop", luv_signal_stop},
{NULL, NULL}
};

static void luv_handle_init(lua_State* L) {

#define XX(uc, lc) \
luaL_newmetatable (L, "uv_"#lc); \
lua_pushcfunction(L, luv_handle_tostring); \
lua_setfield(L, -2, "__tostring"); \
luaL_newlib(L, luv_##lc##_methods); \
luaL_setfuncs(L, luv_handle_methods, 0); \
lua_setfield(L, -2, "__index"); \
lua_pop(L, 1);

UV_HANDLE_TYPE_MAP(XX)
#undef XX

luaL_getmetatable(L, "uv_pipe");
lua_getfield(L, -1, "__index");
luaL_setfuncs(L, luv_stream_methods, 0);
lua_pop(L, 2);

luaL_getmetatable(L, "uv_tcp");
lua_getfield(L, -1, "__index");
luaL_setfuncs(L, luv_stream_methods, 0);
lua_pop(L, 2);

luaL_getmetatable(L, "uv_tty");
lua_getfield(L, -1, "__index");
luaL_setfuncs(L, luv_stream_methods, 0);
lua_pop(L, 2);
}

static lua_State* luv_state(uv_loop_t* loop) {
return loop->data;
}
Expand Down
2 changes: 1 addition & 1 deletion src/pipe.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
#include "luv.h"

static uv_pipe_t* luv_check_pipe(lua_State* L, int index) {
uv_pipe_t* handle = luaL_checkudata(L, index, "uv_handle");
uv_pipe_t* handle = luaL_checkudata(L, index, "uv_pipe");
luaL_argcheck(L, handle->type == UV_NAMED_PIPE && handle->data, index, "Expected uv_pipe_t");
return handle;
}
Expand Down
2 changes: 1 addition & 1 deletion src/poll.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
#include "luv.h"

static uv_poll_t* luv_check_poll(lua_State* L, int index) {
uv_poll_t* handle = luaL_checkudata(L, index, "uv_handle");
uv_poll_t* handle = luaL_checkudata(L, index, "uv_poll");
luaL_argcheck(L, handle->type == UV_POLL && handle->data, index, "Expected uv_poll_t");
return handle;
}
Expand Down
2 changes: 1 addition & 1 deletion src/prepare.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
#include "luv.h"

static uv_prepare_t* luv_check_prepare(lua_State* L, int index) {
uv_prepare_t* handle = luaL_checkudata(L, index, "uv_handle");
uv_prepare_t* handle = luaL_checkudata(L, index, "uv_prepare");
luaL_argcheck(L, handle->type == UV_PREPARE && handle->data, index, "Expected uv_prepare_t");
return handle;
}
Expand Down
3 changes: 2 additions & 1 deletion src/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ static int luv_disable_stdio_inheritance(lua_State* L) {
}

static uv_process_t* luv_check_process(lua_State* L, int index) {
uv_process_t* handle = luaL_checkudata(L, index, "uv_handle");
uv_process_t* handle = luaL_checkudata(L, index, "uv_process");
luaL_argcheck(L, handle->type == UV_PROCESS && handle->data, index, "Expected uv_process_t");
return handle;
}
Expand Down Expand Up @@ -203,6 +203,7 @@ static int luv_spawn(lua_State* L) {
lua_pop(L, 1);

handle = lua_newuserdata(L, sizeof(*handle));
handle->type = UV_PROCESS;
handle->data = luv_setup_handle(L);

if (!lua_isnoneornil(L, 3)) {
Expand Down
2 changes: 1 addition & 1 deletion src/signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
#include "luv.h"

static uv_signal_t* luv_check_signal(lua_State* L, int index) {
uv_signal_t* handle = luaL_checkudata(L, index, "uv_handle");
uv_signal_t* handle = luaL_checkudata(L, index, "uv_signal");
luaL_argcheck(L, handle->type == UV_SIGNAL && handle->data, index, "Expected uv_signal_t");
return handle;
}
Expand Down
19 changes: 12 additions & 7 deletions src/stream.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,18 @@
#include "luv.h"

static uv_stream_t* luv_check_stream(lua_State* L, int index) {
uv_stream_t* handle = luaL_checkudata(L, index, "uv_handle");
luaL_argcheck(L, handle->data && (
handle->type == UV_TCP ||
handle->type == UV_TTY ||
handle->type == UV_NAMED_PIPE),
index, "uv_stream_t subclass required");
return handle;
const uv_handle_t* handle;
luaL_checktype(L, index, LUA_TUSERDATA);
handle = lua_topointer(L, index);
luaL_argcheck(L, handle->data, index, "Expected uv_stream_t");
switch (handle->type) {
case UV_TCP: return luaL_checkudata(L, index, "uv_tcp");
case UV_TTY: return luaL_checkudata(L, index, "uv_tty");
case UV_NAMED_PIPE: return luaL_checkudata(L, index, "uv_pipe");
default:
luaL_argerror(L, index, "Expected uv_stream_t");
return NULL;
}
}

static void luv_shutdown_cb(uv_shutdown_t* req, int status) {
Expand Down
2 changes: 1 addition & 1 deletion src/tcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
#include "luv.h"

static uv_tcp_t* luv_check_tcp(lua_State* L, int index) {
uv_tcp_t* handle = luaL_checkudata(L, index, "uv_handle");
uv_tcp_t* handle = luaL_checkudata(L, index, "uv_tcp");
luaL_argcheck(L, handle->type == UV_TCP && handle->data, index, "Expected uv_tcp_t");
return handle;
}
Expand Down
2 changes: 1 addition & 1 deletion src/timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
#include "luv.h"

static uv_timer_t* luv_check_timer(lua_State* L, int index) {
uv_timer_t* handle = luaL_checkudata(L, index, "uv_handle");
uv_timer_t* handle = luaL_checkudata(L, index, "uv_timer");
luaL_argcheck(L, handle->type == UV_TIMER && handle->data, index, "Expected uv_timer_t");
return handle;
}
Expand Down
2 changes: 1 addition & 1 deletion src/tty.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
#include "luv.h"

static uv_tty_t* luv_check_tty(lua_State* L, int index) {
uv_tty_t* handle = luaL_checkudata(L, index, "uv_handle");
uv_tty_t* handle = luaL_checkudata(L, index, "uv_tty");
luaL_argcheck(L, handle->type == UV_TTY && handle->data, index, "Expected uv_tty_t");
return handle;
}
Expand Down
2 changes: 1 addition & 1 deletion src/udp.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
#include "luv.h"

static uv_udp_t* luv_check_udp(lua_State* L, int index) {
uv_udp_t* handle = luaL_checkudata(L, index, "uv_handle");
uv_udp_t* handle = luaL_checkudata(L, index, "uv_udp");
luaL_argcheck(L, handle->type == UV_UDP && handle->data, index, "Expected uv_udp_t");
return handle;
}
Expand Down
Loading

0 comments on commit 73964e9

Please sign in to comment.