Mercurial > molko
view src/libmlk-core-js/core/js-state.c @ 356:26636fdb735d
js: fix warning
author | David Demelier <markand@malikania.fr> |
---|---|
date | Fri, 22 Oct 2021 10:58:21 +0200 |
parents | 3b2eed504c61 |
children | 39f5d932941a |
line wrap: on
line source
/* * js-state.c -- core state binding * * Copyright (c) 2020-2021 David Demelier <markand@malikania.fr> * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <assert.h> #include <stdlib.h> #include <core/alloc.h> #include <core/state.h> #include "js-event.h" #include "js-state.h" #define SIGNATURE DUK_HIDDEN_SYMBOL("Mlk.State") #define SELF DUK_HIDDEN_SYMBOL("Mlk.State.self") struct self { duk_context *ctx; void *selfptr; struct state state; unsigned int refc; }; static inline int callable(struct self *s, const char *prop, duk_context **ctx) { int callable; duk_push_heapptr(s->ctx, s->selfptr); duk_get_prop_string(s->ctx, -1, prop); duk_remove(s->ctx, -2); if (duk_is_callable(s->ctx, -1)) { *ctx = s->ctx; callable = 1; } else { *ctx = NULL; callable = 0; duk_pop(s->ctx); } return callable; } static void start(struct state *state) { duk_context *ctx; if (callable(state->data, "start", &ctx)) { duk_call(ctx, 0); duk_pop(ctx); } } static void handle(struct state *state, const union event *ev) { duk_context *ctx; if (callable(state->data, "handle", &ctx)) { js_event_push(ctx, ev); duk_call(ctx, 1); duk_pop(ctx); } } static void update(struct state *state, unsigned int ticks) { duk_context *ctx; if (callable(state->data, "update", &ctx)) { duk_push_uint(ctx, ticks); duk_call(ctx, 1); duk_pop(ctx); } } static void draw(struct state *state) { duk_context *ctx; if (callable(state->data, "draw", &ctx)) { duk_call(ctx, 0); duk_pop(ctx); } } static void suspend(struct state *state) { duk_context *ctx; if (callable(state->data, "suspend", &ctx)) { duk_call(ctx, 0); duk_pop(ctx); } } static void resume(struct state *state) { duk_context *ctx; if (callable(state->data, "resume", &ctx)) { duk_call(ctx, 0); duk_pop(ctx); } } static void end(struct state *state) { duk_context *ctx; if (callable(state->data, "end", &ctx)) { duk_call(ctx, 0); duk_pop(ctx); } } static void finish(struct state *state) { struct self *self = state->data; if (!--self->refc) { duk_push_heapptr(self->ctx, self->selfptr); duk_del_prop_string(self->ctx, -1, SIGNATURE); duk_pop(self->ctx); free(self); } } static inline struct self * self(duk_context *ctx) { struct self *data = NULL; duk_push_this(ctx); duk_get_prop_string(ctx, -1, SIGNATURE); data = duk_to_pointer(ctx, -1); duk_pop_2(ctx); if (!data) duk_error(ctx, DUK_ERR_TYPE_ERROR, "not a State object"); return data; } static duk_ret_t State_constructor(duk_context *ctx) { struct self *self; self = alloc_new0(sizeof (*self)); self->ctx = ctx; self->refc = 1; self->state.data = self; self->state.start = start; self->state.handle = handle; self->state.update = update; self->state.draw = draw; self->state.suspend = suspend; self->state.resume = resume; self->state.end = end; self->state.finish = finish; duk_push_this(ctx); self->selfptr = duk_get_heapptr(ctx, -1); duk_dup(ctx, -1); duk_put_prop_string(ctx, -2, SELF); duk_push_pointer(ctx, self); duk_put_prop_string(ctx, -2, SIGNATURE); duk_pop(ctx); return 0; } static duk_ret_t State_destructor(duk_context *ctx) { struct self *self; duk_get_prop_string(ctx, 0, SIGNATURE); if ((self = duk_to_pointer(ctx, -1))) state_finish(&self->state); duk_pop(ctx); return 0; } void js_state_bind(duk_context *ctx) { assert(ctx); duk_push_c_function(ctx, State_constructor, 1); duk_push_object(ctx); duk_push_c_function(ctx, State_destructor, 1); duk_set_finalizer(ctx, -2); duk_put_prop_string(ctx, -2, "prototype"); duk_put_global_string(ctx, "State"); } struct state * js_state_require(duk_context *ctx, duk_idx_t idx) { struct self *self = NULL; if (duk_is_object(ctx, idx)) { duk_get_prop_string(ctx, idx, SIGNATURE); self = duk_to_pointer(ctx, -1); duk_pop(ctx); } if (!self) duk_error(ctx, DUK_ERR_TYPE_ERROR, "not a State object"); self->refc++; return &self->state; }