Compare commits
5 Commits
79685dcdbd
...
5cbcbd4847
Author | SHA1 | Date | |
---|---|---|---|
5cbcbd4847 | |||
fba2172c29 | |||
5046c64ffa | |||
564cc36806 | |||
1d8ff509fe |
@ -1,5 +1,6 @@
|
||||
# ---- basic modules
|
||||
set(MODS
|
||||
lua
|
||||
sdl2
|
||||
test
|
||||
)
|
||||
|
@ -6,25 +6,25 @@ echo "#include <assert.h>"
|
||||
echo
|
||||
echo "#include \"util/log.h\""
|
||||
echo
|
||||
echo "const uint32_t NF7_CORE_MAX_MODS = UINT32_C($#);"
|
||||
echo "const uint32_t NF7CORE_MAX_MODS = UINT32_C($#);"
|
||||
echo
|
||||
echo "uint32_t nf7_core_new(const struct nf7* nf7, struct nf7_mod** mods) {"
|
||||
echo "uint32_t nf7core_new(const struct nf7* nf7, struct nf7_mod** mods) {"
|
||||
echo " assert(nullptr != nf7);"
|
||||
echo " assert(nullptr != mods);"
|
||||
echo
|
||||
echo " uint32_t i = 0;"
|
||||
echo
|
||||
for name in $@; do
|
||||
echo " extern const struct nf7_mod_meta nf7_core_${name};"
|
||||
echo " extern struct nf7_mod* nf7_core_${name}_new(const struct nf7*);"
|
||||
echo " nf7_util_log_debug(\"loading module: %s\", nf7_core_${name}.name);"
|
||||
echo " mods[i] = nf7_core_${name}_new(nf7);"
|
||||
echo " extern const struct nf7_mod_meta nf7core_${name};"
|
||||
echo " extern struct nf7_mod* nf7core_${name}_new(const struct nf7*);"
|
||||
echo " nf7util_log_debug(\"loading module: %s\", nf7core_${name}.name);"
|
||||
echo " mods[i] = nf7core_${name}_new(nf7);"
|
||||
echo " if (nullptr != mods[i]) {"
|
||||
echo " assert(nullptr != mods[i]->meta);"
|
||||
echo " ++i;"
|
||||
echo " nf7_util_log_info(\"loaded module: %s\", nf7_core_${name}.name);"
|
||||
echo " nf7util_log_info(\"loaded module: %s\", nf7core_${name}.name);"
|
||||
echo " } else {"
|
||||
echo " nf7_util_log_warn(\"failed to load module: %s\", nf7_core_${name}.name);"
|
||||
echo " nf7util_log_warn(\"failed to load module: %s\", nf7core_${name}.name);"
|
||||
echo " }"
|
||||
echo
|
||||
done
|
||||
|
@ -6,15 +6,15 @@
|
||||
|
||||
|
||||
// A maximum number of modules which nf7core may provide.
|
||||
extern const uint32_t NF7_CORE_MAX_MODS;
|
||||
extern const uint32_t NF7CORE_MAX_MODS;
|
||||
|
||||
|
||||
// Initializes all modules and returns their instances.
|
||||
uint32_t nf7_core_new(const struct nf7* nf7, struct nf7_mod** mods);
|
||||
uint32_t nf7core_new(const struct nf7* nf7, struct nf7_mod** mods);
|
||||
// PRECONDS:
|
||||
// - `nf7` is a valid pointer
|
||||
// - `mods` is a valid pointer
|
||||
// to memory large enough to keep `NF7_CORE_MAX_MODS` pointers
|
||||
// to memory large enough to keep `nf7core_MAX_MODS` pointers
|
||||
// POSTCONDS:
|
||||
// - When x is lower than the return value,
|
||||
// mods[x] is a valid pointer to an initialized module
|
||||
|
21
core/lua/CMakeLists.txt
Normal file
21
core/lua/CMakeLists.txt
Normal file
@ -0,0 +1,21 @@
|
||||
add_library(nf7core_lua)
|
||||
target_sources(nf7core_lua
|
||||
PRIVATE
|
||||
mod.c
|
||||
thread.c
|
||||
value_ptr.c
|
||||
PUBLIC
|
||||
mod.h
|
||||
thread.h
|
||||
value.h
|
||||
value_ptr.h
|
||||
)
|
||||
target_link_libraries(nf7core_lua
|
||||
PRIVATE
|
||||
nf7if
|
||||
nf7util
|
||||
luajit
|
||||
)
|
||||
target_tests(nf7core_lua
|
||||
thread.test.c
|
||||
)
|
64
core/lua/mod.c
Normal file
64
core/lua/mod.c
Normal file
@ -0,0 +1,64 @@
|
||||
// No copyright
|
||||
#include "core/lua/mod.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "util/log.h"
|
||||
|
||||
#include "core/lua/thread.h"
|
||||
|
||||
|
||||
static void del_(struct nf7core_lua*);
|
||||
|
||||
struct nf7_mod* nf7core_lua_new(struct nf7* nf7) {
|
||||
assert(nullptr != nf7);
|
||||
|
||||
struct nf7core_lua* this =
|
||||
nf7util_malloc_new(nf7->malloc, sizeof(*this));
|
||||
if (nullptr == this) {
|
||||
nf7util_log_error("failed to allocate a module context");
|
||||
goto ABORT;
|
||||
}
|
||||
*this = (struct nf7core_lua) {
|
||||
.meta = &nf7core_lua,
|
||||
.nf7 = nf7,
|
||||
.malloc = nf7->malloc,
|
||||
.uv = nf7->uv,
|
||||
};
|
||||
|
||||
this->thread = nf7core_lua_thread_new(this, nullptr, nullptr);
|
||||
if (nullptr == this->thread) {
|
||||
nf7util_log_error("failed to create main thread");
|
||||
goto ABORT;
|
||||
}
|
||||
return (struct nf7_mod*) this;
|
||||
|
||||
ABORT:
|
||||
nf7util_log_warn("aborting lua module init");
|
||||
del_(this);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static void del_(struct nf7core_lua* this) {
|
||||
if (nullptr == this) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (nullptr != this->thread) {
|
||||
nf7core_lua_thread_unref(this->thread);
|
||||
}
|
||||
nf7util_malloc_del(this->malloc, this);
|
||||
}
|
||||
|
||||
static void del_mod_(struct nf7_mod* mod) {
|
||||
struct nf7core_lua* this = (void*) mod;
|
||||
del_(this);
|
||||
}
|
||||
|
||||
const struct nf7_mod_meta nf7core_lua = {
|
||||
.name = (const uint8_t*) "nf7core_lua",
|
||||
.desc = (const uint8_t*) "lua script execution",
|
||||
.ver = NF7_VERSION,
|
||||
|
||||
.delete = del_mod_,
|
||||
};
|
26
core/lua/mod.h
Normal file
26
core/lua/mod.h
Normal file
@ -0,0 +1,26 @@
|
||||
// No copyright
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <lua.h>
|
||||
|
||||
#include "nf7.h"
|
||||
|
||||
#include "util/malloc.h"
|
||||
#include "util/refcnt.h"
|
||||
|
||||
|
||||
extern const struct nf7_mod_meta nf7core_lua;
|
||||
|
||||
struct nf7core_lua {
|
||||
const struct nf7_mod_meta* meta;
|
||||
|
||||
const struct nf7* nf7;
|
||||
struct nf7util_malloc* malloc;
|
||||
uv_loop_t* uv;
|
||||
|
||||
struct nf7core_lua_thread* thread;
|
||||
};
|
||||
|
||||
struct nf7_mod* nf7core_lua_new(struct nf7*);
|
180
core/lua/thread.c
Normal file
180
core/lua/thread.c
Normal file
@ -0,0 +1,180 @@
|
||||
// No copyright
|
||||
#include "core/lua/thread.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "util/log.h"
|
||||
|
||||
|
||||
static void* alloc_(void*, void*, size_t, size_t);
|
||||
static void del_(struct nf7core_lua_thread*);
|
||||
|
||||
static void on_time_(uv_timer_t*);
|
||||
static void on_close_(uv_handle_t*);
|
||||
|
||||
NF7UTIL_REFCNT_IMPL(, nf7core_lua_thread, {del_(this);});
|
||||
|
||||
struct nf7core_lua_thread* nf7core_lua_thread_new(
|
||||
struct nf7core_lua* mod,
|
||||
struct nf7core_lua_thread* base,
|
||||
struct nf7core_lua_value_ptr* func) {
|
||||
assert(nullptr != mod);
|
||||
|
||||
struct nf7core_lua_thread* this =
|
||||
nf7util_malloc_new(mod->malloc, sizeof(*this));
|
||||
if (nullptr == this) {
|
||||
nf7util_log_error("failed to allocate new thread context");
|
||||
return nullptr;
|
||||
}
|
||||
*this = (struct nf7core_lua_thread) {
|
||||
.mod = mod,
|
||||
.malloc = mod->malloc,
|
||||
.uv = mod->uv,
|
||||
};
|
||||
|
||||
if (0 != nf7util_log_uv(uv_timer_init(this->uv, &this->timer))) {
|
||||
nf7util_log_error("failed to init uv timer");
|
||||
goto ABORT;
|
||||
}
|
||||
this->timer.data = this;
|
||||
|
||||
if (nullptr != base) {
|
||||
this->lua = lua_newthread(base->lua);
|
||||
if (nullptr == this->lua) {
|
||||
nf7util_log_error("failed to allocate new lua thread");
|
||||
goto ABORT;
|
||||
}
|
||||
this->base = base;
|
||||
nf7core_lua_thread_ref(this->base);
|
||||
} else {
|
||||
this->lua_owned = true;
|
||||
this->lua = lua_newstate(alloc_, this);
|
||||
if (nullptr == this->lua) {
|
||||
nf7util_log_error("failed to allocate new lua state");
|
||||
goto ABORT;
|
||||
}
|
||||
nf7util_log_debug("new lua state is created");
|
||||
}
|
||||
|
||||
if (nullptr != func) {
|
||||
this->state = NF7CORE_LUA_THREAD_PAUSED;
|
||||
nf7core_lua_value_ptr_push(func, this->lua);
|
||||
} else {
|
||||
this->state = NF7CORE_LUA_THREAD_DONE;
|
||||
}
|
||||
|
||||
nf7core_lua_thread_ref(this);
|
||||
return this;
|
||||
|
||||
ABORT:
|
||||
nf7util_log_warn("aborting thread creation");
|
||||
del_(this);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool nf7core_lua_thread_resume_varg_after(
|
||||
struct nf7core_lua_thread* this, uint64_t timeout, va_list vargs) {
|
||||
assert(nullptr != this);
|
||||
assert(NF7CORE_LUA_THREAD_PAUSED == this->state);
|
||||
|
||||
// stores parameters
|
||||
for (uint32_t i = 0;; ++i) {
|
||||
struct nf7core_lua_value* src = va_arg(vargs, struct nf7core_lua_value*);
|
||||
if (nullptr == src) {
|
||||
this->args.n = i;
|
||||
break;
|
||||
}
|
||||
assert(i < NF7CORE_LUA_THREAD_MAX_ARGS &&
|
||||
"too many args or forgotten last nullptr");
|
||||
|
||||
struct nf7core_lua_value* dst = &this->args.ptr[i];
|
||||
if (!nf7core_lua_value_set(dst, src)) {
|
||||
nf7core_lua_value_set(dst, &NF7CORE_LUA_VALUE_NIL());
|
||||
nf7util_log_warn(
|
||||
"failed to store parameter value, it's replaced by nil");
|
||||
}
|
||||
}
|
||||
|
||||
if (0 != nf7util_log_uv(uv_timer_start(&this->timer, on_time_, timeout, 0))) {
|
||||
nf7util_log_error(
|
||||
"failed to start timer for resuming thread");
|
||||
return false;
|
||||
}
|
||||
nf7core_lua_thread_ref(this);
|
||||
|
||||
nf7util_log_debug("lua thread state change: PAUSED -> SCHEDULED");
|
||||
this->state = NF7CORE_LUA_THREAD_SCHEDULED;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void* alloc_(void* data, void* ptr, size_t, size_t nsize) {
|
||||
struct nf7core_lua_thread* this = data;
|
||||
return nf7util_malloc_renew(this->malloc, ptr, nsize);
|
||||
}
|
||||
|
||||
static void del_(struct nf7core_lua_thread* this) {
|
||||
if (nullptr == this) {
|
||||
return;
|
||||
}
|
||||
if (nullptr != this->timer.data) {
|
||||
uv_close((uv_handle_t*) &this->timer, on_close_);
|
||||
return;
|
||||
}
|
||||
|
||||
if (nullptr != this->lua && this->lua_owned) {
|
||||
lua_close(this->lua);
|
||||
nf7util_log_debug("lua state is closed");
|
||||
}
|
||||
if (nullptr != this->base) {
|
||||
nf7core_lua_thread_unref(this->base);
|
||||
}
|
||||
nf7util_malloc_del(this->malloc, this);
|
||||
}
|
||||
|
||||
static void on_time_(uv_timer_t* timer) {
|
||||
struct nf7core_lua_thread* this = timer->data;
|
||||
assert(nullptr != this);
|
||||
assert(NF7CORE_LUA_THREAD_SCHEDULED == this->state);
|
||||
|
||||
lua_State* L = this->lua;
|
||||
for (uint32_t i = 0; i < this->args.n; ++i) {
|
||||
struct nf7core_lua_value* v = &this->args.ptr[i];
|
||||
nf7core_lua_value_push(v, L);
|
||||
nf7core_lua_value_unset(v);
|
||||
}
|
||||
|
||||
nf7util_log_debug("lua thread state change: SCHEDULED -> RUNNING");
|
||||
this->state = NF7CORE_LUA_THREAD_RUNNING;
|
||||
|
||||
const int result = lua_resume(L, (int) this->args.n);
|
||||
switch (result) {
|
||||
case 0:
|
||||
nf7util_log_debug("lua thread state change: RUNNING -> DONE");
|
||||
this->state = NF7CORE_LUA_THREAD_DONE;
|
||||
break;
|
||||
case LUA_YIELD:
|
||||
nf7util_log_debug("lua thread state change: RUNNING -> PAUSED");
|
||||
this->state = NF7CORE_LUA_THREAD_PAUSED;
|
||||
break;
|
||||
case LUA_ERRMEM:
|
||||
case LUA_ERRRUN:
|
||||
case LUA_ERRERR:
|
||||
nf7util_log_warn("lua execution failed: ", lua_tostring(L, -1));
|
||||
nf7util_log_debug("lua thread state change: RUNNING -> ABORTED");
|
||||
this->state = NF7CORE_LUA_THREAD_ABORTED;
|
||||
break;
|
||||
}
|
||||
|
||||
if (nullptr != this->post_exec) {
|
||||
this->post_exec(this, L);
|
||||
}
|
||||
lua_settop(L, 0);
|
||||
|
||||
nf7core_lua_thread_unref(this);
|
||||
}
|
||||
|
||||
static void on_close_(uv_handle_t* handle) {
|
||||
struct nf7core_lua_thread* this = handle->data;
|
||||
this->timer.data = nullptr;
|
||||
del_(this);
|
||||
}
|
92
core/lua/thread.h
Normal file
92
core/lua/thread.h
Normal file
@ -0,0 +1,92 @@
|
||||
// No copyright
|
||||
#pragma once
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <lua.h>
|
||||
#include <uv.h>
|
||||
|
||||
#include "util/malloc.h"
|
||||
#include "util/refcnt.h"
|
||||
|
||||
#include "core/lua/mod.h"
|
||||
#include "core/lua/value.h"
|
||||
#include "core/lua/value_ptr.h"
|
||||
|
||||
|
||||
struct nf7core_lua_thread {
|
||||
struct nf7core_lua* mod;
|
||||
struct nf7util_malloc* malloc;
|
||||
uv_loop_t* uv;
|
||||
|
||||
bool lua_owned;
|
||||
lua_State* lua;
|
||||
|
||||
struct nf7core_lua_thread* base;
|
||||
|
||||
uv_timer_t timer;
|
||||
|
||||
uint32_t refcnt;
|
||||
|
||||
uint8_t state;
|
||||
# define NF7CORE_LUA_THREAD_PAUSED 0
|
||||
# define NF7CORE_LUA_THREAD_SCHEDULED 1
|
||||
# define NF7CORE_LUA_THREAD_RUNNING 2
|
||||
# define NF7CORE_LUA_THREAD_DONE 3
|
||||
# define NF7CORE_LUA_THREAD_ABORTED 4
|
||||
|
||||
struct {
|
||||
# define NF7CORE_LUA_THREAD_MAX_ARGS 4
|
||||
uint32_t n;
|
||||
struct nf7core_lua_value ptr[NF7CORE_LUA_THREAD_MAX_ARGS];
|
||||
} args;
|
||||
|
||||
void* data;
|
||||
void (*post_exec)(struct nf7core_lua_thread*, lua_State*);
|
||||
};
|
||||
NF7UTIL_REFCNT_DECL(, nf7core_lua_thread);
|
||||
|
||||
|
||||
// Creates and returns new thread.
|
||||
struct nf7core_lua_thread* nf7core_lua_thread_new(
|
||||
struct nf7core_lua* mod,
|
||||
struct nf7core_lua_thread* base,
|
||||
struct nf7core_lua_value_ptr* func);
|
||||
// POSTCONDS:
|
||||
// - If the base is not nullptr, the returned thread must be synchronized with
|
||||
// the base, otherwise, it's completely independent. (base thread)
|
||||
// - If the func is not nullptr, the returned thread prepares to execute a
|
||||
// function in the value,
|
||||
// otherwise, it can execute nothing (this is for the base thread)
|
||||
|
||||
// Resumes the co-routine with the values.
|
||||
bool nf7core_lua_thread_resume_varg_after(
|
||||
struct nf7core_lua_thread* this, uint64_t timeout, va_list vargs);
|
||||
// PRECONDS:
|
||||
// - `nullptr != this`
|
||||
// - `nullptr != this->func`
|
||||
// - `NF7CORE_LUA_THREAD_PAUSED == this->state`
|
||||
// - Items in `vargs` must be `const struct nf7core_lua_value*` or `nullptr`.
|
||||
// - The last item of `vargs` must be `nullptr`.
|
||||
// POSTCONDS:
|
||||
// - When returns true:
|
||||
// - `NF7CORE_LUA_THREAD_SCHEDULED == this->state`
|
||||
// - the state will changes to RUNNING after `timeout` [ms]
|
||||
// - Otherwise, nothing happens.
|
||||
|
||||
static inline bool nf7core_lua_thread_resume(
|
||||
struct nf7core_lua_thread* this, ...) {
|
||||
va_list vargs;
|
||||
va_start(vargs, this);
|
||||
const bool ret = nf7core_lua_thread_resume_varg_after(this, 0, vargs);
|
||||
va_end(vargs);
|
||||
return ret;
|
||||
}
|
||||
static inline bool nf7core_lua_thread_resume_after(
|
||||
struct nf7core_lua_thread* this, uint64_t timeout, ...) {
|
||||
va_list vargs;
|
||||
va_start(vargs, this);
|
||||
const bool ret = nf7core_lua_thread_resume_varg_after(this, timeout, vargs);
|
||||
va_end(vargs);
|
||||
return ret;
|
||||
}
|
67
core/lua/thread.test.c
Normal file
67
core/lua/thread.test.c
Normal file
@ -0,0 +1,67 @@
|
||||
// No copyright
|
||||
#include "core/lua/thread.h"
|
||||
|
||||
#include <lauxlib.h>
|
||||
|
||||
#include "util/log.h"
|
||||
|
||||
#include "test/common.h"
|
||||
|
||||
|
||||
static void finalize_(struct nf7core_lua_thread* this, lua_State*) {
|
||||
struct nf7test* test_ = this->data;
|
||||
nf7test_expect(NF7CORE_LUA_THREAD_DONE == this->state);
|
||||
nf7test_unref(test_);
|
||||
}
|
||||
|
||||
NF7TEST(nf7core_lua_thread_test_valid_syntax) {
|
||||
struct nf7core_lua* mod =
|
||||
(void*) nf7_get_mod_by_meta(test_->nf7, &nf7core_lua);
|
||||
if (!nf7test_expect(nullptr != mod)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
struct nf7core_lua_thread* base = mod->thread;
|
||||
lua_State* L = base->lua;
|
||||
|
||||
if (!nf7test_expect(0 == luaL_loadstring(L, "local x = 100"))) {
|
||||
nf7util_log_error("lua compile error: %s", lua_tostring(L, -1));
|
||||
return false;
|
||||
}
|
||||
|
||||
struct nf7core_lua_value_ptr* func = nf7core_lua_value_ptr_new(base, L);
|
||||
if (!nf7test_expect(nullptr != func)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
struct nf7core_lua_thread* thread = nf7core_lua_thread_new(mod, base, func);
|
||||
nf7core_lua_value_ptr_unref(func);
|
||||
if (!nf7test_expect(nullptr != thread)) {
|
||||
return false;
|
||||
}
|
||||
thread->data = test_;
|
||||
thread->post_exec = finalize_;
|
||||
|
||||
if (!nf7test_expect(nf7core_lua_thread_resume(thread, nullptr))) {
|
||||
return false;
|
||||
}
|
||||
nf7core_lua_thread_unref(thread);
|
||||
nf7test_ref(test_);
|
||||
return true;
|
||||
}
|
||||
|
||||
NF7TEST(nf7core_lua_thread_test_invalid_syntax) {
|
||||
struct nf7core_lua* mod =
|
||||
(void*) nf7_get_mod_by_meta(test_->nf7, &nf7core_lua);
|
||||
if (!nf7test_expect(nullptr != mod)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
struct nf7core_lua_thread* base = mod->thread;
|
||||
lua_State* L = base->lua;
|
||||
|
||||
if (!nf7test_expect(0 != luaL_loadstring(L, "helloworld"))) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
88
core/lua/value.h
Normal file
88
core/lua/value.h
Normal file
@ -0,0 +1,88 @@
|
||||
// No copyright
|
||||
#pragma once
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "core/lua/value_ptr.h"
|
||||
|
||||
|
||||
struct nf7core_lua_value {
|
||||
uint32_t type;
|
||||
# define NF7CORE_LUA_VALUE_TYPE_NIL 0
|
||||
# define NF7CORE_LUA_VALUE_TYPE_INT 1
|
||||
# define NF7CORE_LUA_VALUE_TYPE_NUM 2
|
||||
# define NF7CORE_LUA_VALUE_TYPE_PTR 3
|
||||
union {
|
||||
lua_Integer i;
|
||||
lua_Number n;
|
||||
struct nf7core_lua_value_ptr* ptr;
|
||||
};
|
||||
};
|
||||
|
||||
#define NF7CORE_LUA_VALUE_NIL() \
|
||||
(struct nf7core_lua_value) { .type = NF7CORE_LUA_VALUE_TYPE_NIL, }
|
||||
#define NF7CORE_LUA_VALUE_INT(v) \
|
||||
(struct nf7core_lua_value) { .type = NF7CORE_LUA_VALUE_TYPE_INT, .i = (v), }
|
||||
#define NF7CORE_LUA_VALUE_NUM(v) \
|
||||
(struct nf7core_lua_value) { .type = NF7CORE_LUA_VALUE_TYPE_NUM, .n = (v), }
|
||||
#define NF7CORE_LUA_VALUE_PTR(v) \
|
||||
(struct nf7core_lua_value) { \
|
||||
.type = NF7CORE_LUA_VALUE_TYPE_PTR, \
|
||||
.ptr = (v), \
|
||||
}
|
||||
|
||||
static inline void nf7core_lua_value_push(
|
||||
const struct nf7core_lua_value* this, lua_State* L) {
|
||||
assert(nullptr != this);
|
||||
assert(nullptr != L);
|
||||
|
||||
switch (this->type) {
|
||||
case NF7CORE_LUA_VALUE_TYPE_NIL:
|
||||
lua_pushnil(L);
|
||||
break;
|
||||
case NF7CORE_LUA_VALUE_TYPE_INT:
|
||||
lua_pushinteger(L, this->i);
|
||||
break;
|
||||
case NF7CORE_LUA_VALUE_TYPE_NUM:
|
||||
lua_pushnumber(L, this->n);
|
||||
break;
|
||||
case NF7CORE_LUA_VALUE_TYPE_PTR:
|
||||
assert(nullptr != this->ptr);
|
||||
nf7core_lua_value_ptr_push(this->ptr, L);
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void nf7core_lua_value_unset(struct nf7core_lua_value* this) {
|
||||
assert(nullptr != this);
|
||||
|
||||
switch (this->type) {
|
||||
case NF7CORE_LUA_VALUE_TYPE_PTR:
|
||||
nf7core_lua_value_ptr_unref(this->ptr);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
this->type = NF7CORE_LUA_VALUE_TYPE_NIL;
|
||||
}
|
||||
|
||||
static inline bool nf7core_lua_value_set(
|
||||
struct nf7core_lua_value* this, const struct nf7core_lua_value* src) {
|
||||
assert(nullptr != this);
|
||||
assert(nullptr != src);
|
||||
|
||||
nf7core_lua_value_unset(this);
|
||||
|
||||
switch (src->type) {
|
||||
case NF7CORE_LUA_VALUE_TYPE_PTR:
|
||||
*this = *src;
|
||||
nf7core_lua_value_ptr_ref(this->ptr);
|
||||
return true;
|
||||
default:
|
||||
*this = *src;
|
||||
return true;
|
||||
}
|
||||
}
|
64
core/lua/value_ptr.c
Normal file
64
core/lua/value_ptr.c
Normal file
@ -0,0 +1,64 @@
|
||||
// No copyright
|
||||
#include "core/lua/value_ptr.h"
|
||||
|
||||
#include <lua.h>
|
||||
#include <lauxlib.h>
|
||||
|
||||
#include "core/lua/thread.h"
|
||||
|
||||
|
||||
struct nf7core_lua_value_ptr {
|
||||
struct nf7core_lua_thread* thread;
|
||||
struct nf7util_malloc* malloc;
|
||||
lua_State* lua;
|
||||
|
||||
uint32_t refcnt;
|
||||
int index;
|
||||
};
|
||||
|
||||
static void del_(struct nf7core_lua_value_ptr*);
|
||||
|
||||
NF7UTIL_REFCNT_IMPL(, nf7core_lua_value_ptr, {del_(this);});
|
||||
|
||||
|
||||
struct nf7core_lua_value_ptr* nf7core_lua_value_ptr_new(
|
||||
struct nf7core_lua_thread* thread, lua_State* L) {
|
||||
assert(nullptr != thread);
|
||||
assert(nullptr != L);
|
||||
|
||||
struct nf7core_lua_value_ptr* this =
|
||||
nf7util_malloc_new(thread->malloc, sizeof(*this));
|
||||
if (nullptr == this) {
|
||||
goto ABORT;
|
||||
}
|
||||
*this = (struct nf7core_lua_value_ptr) {
|
||||
.malloc = thread->malloc,
|
||||
.lua = L,
|
||||
};
|
||||
|
||||
this->thread = thread;
|
||||
nf7core_lua_thread_ref(this->thread);
|
||||
|
||||
this->index = luaL_ref(this->lua, LUA_REGISTRYINDEX);
|
||||
|
||||
nf7core_lua_value_ptr_ref(this);
|
||||
return this;
|
||||
|
||||
ABORT:
|
||||
lua_pop(L, 1);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void nf7core_lua_value_ptr_push(
|
||||
const struct nf7core_lua_value_ptr* this, lua_State* lua) {
|
||||
assert(nullptr != this);
|
||||
assert(nullptr != lua);
|
||||
lua_rawgeti(lua, LUA_REGISTRYINDEX, this->index);
|
||||
}
|
||||
|
||||
static void del_(struct nf7core_lua_value_ptr* this) {
|
||||
assert(nullptr != this);
|
||||
luaL_unref(this->lua, LUA_REGISTRYINDEX, this->index);
|
||||
nf7core_lua_thread_unref(this->thread);
|
||||
nf7util_malloc_del(this->malloc, this);
|
||||
}
|
22
core/lua/value_ptr.h
Normal file
22
core/lua/value_ptr.h
Normal file
@ -0,0 +1,22 @@
|
||||
// No copyright
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <lua.h>
|
||||
|
||||
#include "util/refcnt.h"
|
||||
|
||||
|
||||
struct nf7core_lua_thread;
|
||||
|
||||
struct nf7core_lua_value_ptr;
|
||||
NF7UTIL_REFCNT_DECL(, nf7core_lua_value_ptr);
|
||||
|
||||
struct nf7core_lua_value_ptr* nf7core_lua_value_ptr_new(
|
||||
struct nf7core_lua_thread*, lua_State*);
|
||||
// POSTCONDS:
|
||||
// - the top value is always popped
|
||||
|
||||
void nf7core_lua_value_ptr_push(
|
||||
const struct nf7core_lua_value_ptr*, lua_State*);
|
@ -18,31 +18,31 @@
|
||||
static atomic_uint_least32_t sdl_refcnt_ = 0;
|
||||
|
||||
|
||||
static void poll_(struct nf7_core_sdl2_poll*, const SDL_Event*);
|
||||
static void del_(struct nf7_core_sdl2*);
|
||||
NF7_UTIL_REFCNT_IMPL(, nf7_core_sdl2, {del_(this);});
|
||||
static void poll_(struct nf7core_sdl2_poll*, const SDL_Event*);
|
||||
static void del_(struct nf7core_sdl2*);
|
||||
NF7UTIL_REFCNT_IMPL(, nf7core_sdl2, {del_(this);});
|
||||
|
||||
|
||||
struct nf7_mod* nf7_core_sdl2_new(const struct nf7* nf7) {
|
||||
struct nf7_mod* nf7core_sdl2_new(const struct nf7* nf7) {
|
||||
assert(nullptr != nf7);
|
||||
|
||||
if (0 < atomic_fetch_add(&sdl_refcnt_, 1)) {
|
||||
nf7_util_log_error(
|
||||
nf7util_log_error(
|
||||
"multiple SDL2 module instance cannot be exists at the same time");
|
||||
return nullptr;
|
||||
}
|
||||
if (0 != SDL_Init(SDL_INIT_VIDEO)) {
|
||||
nf7_util_log_error("failed to init SDL: %s", SDL_GetError());
|
||||
nf7util_log_error("failed to init SDL: %s", SDL_GetError());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
struct nf7_core_sdl2* this = nf7_util_malloc_new(nf7->malloc, sizeof(*this));
|
||||
struct nf7core_sdl2* this = nf7util_malloc_new(nf7->malloc, sizeof(*this));
|
||||
if (nullptr == this) {
|
||||
nf7_util_log_error("failed to allocate instance");
|
||||
nf7util_log_error("failed to allocate instance");
|
||||
goto ABORT;
|
||||
}
|
||||
*this = (struct nf7_core_sdl2) {
|
||||
.meta = &nf7_core_sdl2,
|
||||
*this = (struct nf7core_sdl2) {
|
||||
.meta = &nf7core_sdl2,
|
||||
.nf7 = nf7,
|
||||
.malloc = nf7->malloc,
|
||||
.uv = nf7->uv,
|
||||
@ -53,54 +53,54 @@ struct nf7_mod* nf7_core_sdl2_new(const struct nf7* nf7) {
|
||||
|
||||
this->poll = poll_new_(this);
|
||||
if (nullptr == this->poll) {
|
||||
nf7_util_log_error("failed to setup polling");
|
||||
nf7util_log_error("failed to setup polling");
|
||||
goto ABORT;
|
||||
}
|
||||
this->poll->data = this;
|
||||
this->poll->handler = poll_;
|
||||
|
||||
nf7_util_signal_init(&this->event_signal);
|
||||
nf7_core_sdl2_ref(this);
|
||||
nf7util_signal_init(&this->event_signal);
|
||||
nf7core_sdl2_ref(this);
|
||||
return (struct nf7_mod*) this;
|
||||
|
||||
ABORT:
|
||||
nf7_util_log_warn("initialization is aborted");
|
||||
nf7util_log_warn("initialization is aborted");
|
||||
del_(this);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static void poll_(struct nf7_core_sdl2_poll* poll, const SDL_Event* e) {
|
||||
struct nf7_core_sdl2* this = poll->data;
|
||||
static void poll_(struct nf7core_sdl2_poll* poll, const SDL_Event* e) {
|
||||
struct nf7core_sdl2* this = poll->data;
|
||||
this->event = e;
|
||||
nf7_util_signal_emit(&this->event_signal);
|
||||
nf7util_signal_emit(&this->event_signal);
|
||||
this->event = nullptr;
|
||||
}
|
||||
|
||||
static void del_(struct nf7_core_sdl2* this) {
|
||||
static void del_(struct nf7core_sdl2* this) {
|
||||
if (nullptr == this) {
|
||||
return;
|
||||
}
|
||||
|
||||
nf7_util_signal_deinit(&this->event_signal);
|
||||
nf7util_signal_deinit(&this->event_signal);
|
||||
poll_del_(this->poll);
|
||||
nf7_util_malloc_del(this->malloc, this);
|
||||
nf7util_malloc_del(this->malloc, this);
|
||||
|
||||
if (1 == atomic_fetch_sub(&sdl_refcnt_, 1)) {
|
||||
nf7_util_log_debug("finalizing SDL...");
|
||||
nf7util_log_debug("finalizing SDL...");
|
||||
SDL_Quit();
|
||||
nf7_util_log_info("SDL is finalized");
|
||||
nf7util_log_info("SDL is finalized");
|
||||
}
|
||||
}
|
||||
|
||||
static void unref_(struct nf7_mod* this_) {
|
||||
struct nf7_core_sdl2* this = (struct nf7_core_sdl2*) this_;
|
||||
nf7_core_sdl2_unref(this);
|
||||
struct nf7core_sdl2* this = (struct nf7core_sdl2*) this_;
|
||||
nf7core_sdl2_unref(this);
|
||||
}
|
||||
|
||||
const struct nf7_mod_meta nf7_core_sdl2 = {
|
||||
const struct nf7_mod_meta nf7core_sdl2 = {
|
||||
.name = (const uint8_t*) "nf7core_sdl2",
|
||||
.desc = (const uint8_t*) "provides SDL2 features",
|
||||
.ver = 0,
|
||||
.ver = NF7_VERSION,
|
||||
|
||||
.delete = unref_,
|
||||
};
|
||||
|
@ -13,24 +13,24 @@
|
||||
#include "util/signal.h"
|
||||
|
||||
|
||||
extern const struct nf7_mod_meta nf7_core_sdl2;
|
||||
extern const struct nf7_mod_meta nf7core_sdl2;
|
||||
|
||||
struct nf7_core_sdl2_poll;
|
||||
struct nf7core_sdl2_poll;
|
||||
|
||||
struct nf7_core_sdl2 {
|
||||
struct nf7core_sdl2 {
|
||||
const struct nf7_mod_meta* meta;
|
||||
|
||||
// library pointers (immutable)
|
||||
const struct nf7* nf7;
|
||||
struct nf7_util_malloc* malloc;
|
||||
uv_loop_t* uv;
|
||||
SDL_Window* win;
|
||||
void* gl;
|
||||
const struct nf7* nf7;
|
||||
struct nf7util_malloc* malloc;
|
||||
uv_loop_t* uv;
|
||||
SDL_Window* win;
|
||||
void* gl;
|
||||
|
||||
uint32_t refcnt;
|
||||
|
||||
struct nf7_core_sdl2_poll* poll;
|
||||
struct nf7core_sdl2_poll* poll;
|
||||
const SDL_Event* event;
|
||||
struct nf7_util_signal event_signal;
|
||||
struct nf7util_signal event_signal;
|
||||
};
|
||||
NF7_UTIL_REFCNT_DECL(, nf7_core_sdl2);
|
||||
NF7UTIL_REFCNT_DECL(, nf7core_sdl2);
|
||||
|
@ -8,36 +8,36 @@
|
||||
#include "core/sdl2/mod.h"
|
||||
|
||||
|
||||
struct nf7_core_sdl2_poll {
|
||||
struct nf7core_sdl2_poll {
|
||||
const struct nf7* nf7;
|
||||
struct nf7_util_malloc* malloc;
|
||||
struct nf7util_malloc* malloc;
|
||||
uv_loop_t* uv;
|
||||
|
||||
uv_timer_t timer;
|
||||
uint64_t interval;
|
||||
|
||||
void* data;
|
||||
void (*handler)(struct nf7_core_sdl2_poll*, const SDL_Event*);
|
||||
void (*handler)(struct nf7core_sdl2_poll*, const SDL_Event*);
|
||||
};
|
||||
|
||||
|
||||
static struct nf7_core_sdl2_poll* poll_new_(struct nf7_core_sdl2*);
|
||||
static void poll_del_(struct nf7_core_sdl2_poll*);
|
||||
static struct nf7core_sdl2_poll* poll_new_(struct nf7core_sdl2*);
|
||||
static void poll_del_(struct nf7core_sdl2_poll*);
|
||||
|
||||
static void poll_on_time_(uv_timer_t*);
|
||||
static void poll_on_close_(uv_handle_t*);
|
||||
|
||||
|
||||
static struct nf7_core_sdl2_poll* poll_new_(struct nf7_core_sdl2* mod) {
|
||||
static struct nf7core_sdl2_poll* poll_new_(struct nf7core_sdl2* mod) {
|
||||
assert(nullptr != mod);
|
||||
|
||||
struct nf7_core_sdl2_poll* this =
|
||||
nf7_util_malloc_new(mod->malloc, sizeof(*this));
|
||||
struct nf7core_sdl2_poll* this =
|
||||
nf7util_malloc_new(mod->malloc, sizeof(*this));
|
||||
if (nullptr == this) {
|
||||
nf7_util_log_error("failed to allocate poll context");
|
||||
nf7util_log_error("failed to allocate poll context");
|
||||
return nullptr;
|
||||
}
|
||||
*this = (struct nf7_core_sdl2_poll) {
|
||||
*this = (struct nf7core_sdl2_poll) {
|
||||
.nf7 = mod->nf7,
|
||||
.malloc = mod->malloc,
|
||||
.uv = mod->uv,
|
||||
@ -45,21 +45,21 @@ static struct nf7_core_sdl2_poll* poll_new_(struct nf7_core_sdl2* mod) {
|
||||
.interval = 30,
|
||||
};
|
||||
|
||||
if (0 != nf7_util_log_uv(uv_timer_init(this->uv, &this->timer))) {
|
||||
nf7_util_log_error("failed to init poll timer");
|
||||
if (0 != nf7util_log_uv(uv_timer_init(this->uv, &this->timer))) {
|
||||
nf7util_log_error("failed to init poll timer");
|
||||
return nullptr;
|
||||
}
|
||||
uv_unref((uv_handle_t*) &this->timer);
|
||||
this->timer.data = this;
|
||||
|
||||
if (0 != nf7_util_log_uv(uv_timer_start(&this->timer, poll_on_time_, 0, 0))) {
|
||||
nf7_util_log_error("failed to start poll timer");
|
||||
if (0 != nf7util_log_uv(uv_timer_start(&this->timer, poll_on_time_, 0, 0))) {
|
||||
nf7util_log_error("failed to start poll timer");
|
||||
poll_del_(this);
|
||||
return nullptr;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
static void poll_del_(struct nf7_core_sdl2_poll* this) {
|
||||
static void poll_del_(struct nf7core_sdl2_poll* this) {
|
||||
if (this == nullptr) {
|
||||
return;
|
||||
}
|
||||
@ -68,13 +68,13 @@ static void poll_del_(struct nf7_core_sdl2_poll* this) {
|
||||
uv_close((uv_handle_t*) &this->timer, poll_on_close_);
|
||||
return;
|
||||
}
|
||||
nf7_util_malloc_del(this->malloc, this);
|
||||
nf7util_malloc_del(this->malloc, this);
|
||||
}
|
||||
|
||||
static void poll_on_time_(uv_timer_t* timer) {
|
||||
assert(nullptr != timer);
|
||||
|
||||
struct nf7_core_sdl2_poll* this = timer->data;
|
||||
struct nf7core_sdl2_poll* this = timer->data;
|
||||
|
||||
SDL_Event e;
|
||||
while (0 != SDL_PollEvent(&e)) {
|
||||
@ -84,13 +84,13 @@ static void poll_on_time_(uv_timer_t* timer) {
|
||||
}
|
||||
|
||||
if (0 != uv_timer_start(&this->timer, poll_on_time_, this->interval, 0)) {
|
||||
nf7_util_log_error("failed to restart poll timer");
|
||||
nf7util_log_error("failed to restart poll timer");
|
||||
poll_del_(this);
|
||||
}
|
||||
}
|
||||
|
||||
static void poll_on_close_(uv_handle_t* handle) {
|
||||
struct nf7_core_sdl2_poll* this = handle->data;
|
||||
struct nf7core_sdl2_poll* this = handle->data;
|
||||
assert(nullptr != this);
|
||||
handle->data = nullptr;
|
||||
poll_del_(this);
|
||||
|
@ -9,23 +9,23 @@
|
||||
|
||||
|
||||
static void setup_gl_(void);
|
||||
static void handle_(struct nf7_util_signal_recv* recv);
|
||||
static void handle_(struct nf7util_signal_recv* recv);
|
||||
|
||||
|
||||
bool nf7_core_sdl2_win_init(struct nf7_core_sdl2_win* this) {
|
||||
bool nf7core_sdl2_win_init(struct nf7core_sdl2_win* this) {
|
||||
assert(nullptr != this);
|
||||
assert(nullptr != this->mod);
|
||||
assert(nullptr != this->malloc);
|
||||
|
||||
// TODO error handling
|
||||
|
||||
this->event_recv = (struct nf7_util_signal_recv) {
|
||||
this->event_recv = (struct nf7util_signal_recv) {
|
||||
.signal = &this->mod->event_signal,
|
||||
};
|
||||
this->event_recv.data = this;
|
||||
this->event_recv.func = handle_;
|
||||
if (!nf7_util_signal_recv_set(&this->event_recv, &this->mod->event_signal)) {
|
||||
nf7_util_log_error("failed to listen event signal");
|
||||
if (!nf7util_signal_recv_set(&this->event_recv, &this->mod->event_signal)) {
|
||||
nf7util_log_error("failed to listen event signal");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -41,45 +41,45 @@ bool nf7_core_sdl2_win_init(struct nf7_core_sdl2_win* this) {
|
||||
1280, 720,
|
||||
SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
|
||||
if (nullptr == this->win) {
|
||||
nf7_util_log_error("failed to create SDL window: %s", SDL_GetError());
|
||||
nf7util_log_error("failed to create SDL window: %s", SDL_GetError());
|
||||
return false;
|
||||
}
|
||||
this->win_id = SDL_GetWindowID(this->win);
|
||||
if (0 == this->win_id) {
|
||||
nf7_util_log_error("failed to get window id: %s", SDL_GetError());
|
||||
nf7util_log_error("failed to get window id: %s", SDL_GetError());
|
||||
return false;
|
||||
}
|
||||
nf7_util_log_debug("GUI window %" PRIu32 " is created", this->win_id);
|
||||
nf7util_log_debug("GUI window %" PRIu32 " is created", this->win_id);
|
||||
|
||||
this->gl = SDL_GL_CreateContext(this->win);
|
||||
if (nullptr == this->gl) {
|
||||
nf7_util_log_error("failed to create GL context: %s", SDL_GetError());
|
||||
nf7util_log_error("failed to create GL context: %s", SDL_GetError());
|
||||
return false;
|
||||
}
|
||||
nf7_util_log_debug("OpenGL context is created");
|
||||
nf7util_log_debug("OpenGL context is created");
|
||||
|
||||
if (0 != SDL_GL_SetSwapInterval(0)) {
|
||||
nf7_util_log_warn(
|
||||
nf7util_log_warn(
|
||||
"failed to set swap interval, this will cause a performance issue: %s",
|
||||
SDL_GetError());
|
||||
}
|
||||
|
||||
nf7_core_sdl2_ref(this->mod);
|
||||
nf7core_sdl2_ref(this->mod);
|
||||
return true;
|
||||
}
|
||||
|
||||
void nf7_core_sdl2_win_deinit(struct nf7_core_sdl2_win* this) {
|
||||
void nf7core_sdl2_win_deinit(struct nf7core_sdl2_win* this) {
|
||||
if (nullptr != this) {
|
||||
if (nullptr != this->gl) {
|
||||
SDL_GL_DeleteContext(this->gl);
|
||||
nf7_util_log_debug("OpenGL context is deleted");
|
||||
nf7util_log_debug("OpenGL context is deleted");
|
||||
}
|
||||
if (nullptr != this->win) {
|
||||
SDL_DestroyWindow(this->win);
|
||||
nf7_util_log_debug("GUI window is destroyed");
|
||||
nf7util_log_debug("GUI window is destroyed");
|
||||
}
|
||||
nf7_util_signal_recv_unset(&this->event_recv);
|
||||
nf7_core_sdl2_unref(this->mod);
|
||||
nf7util_signal_recv_unset(&this->event_recv);
|
||||
nf7core_sdl2_unref(this->mod);
|
||||
}
|
||||
}
|
||||
|
||||
@ -97,8 +97,8 @@ static void setup_gl_(void) {
|
||||
# endif
|
||||
}
|
||||
|
||||
static void handle_(struct nf7_util_signal_recv* recv) {
|
||||
struct nf7_core_sdl2_win* this = recv->data;
|
||||
static void handle_(struct nf7util_signal_recv* recv) {
|
||||
struct nf7core_sdl2_win* this = recv->data;
|
||||
assert(nullptr != this);
|
||||
|
||||
const SDL_Event* e = this->mod->event;
|
||||
@ -113,7 +113,7 @@ static void handle_(struct nf7_util_signal_recv* recv) {
|
||||
|
||||
switch (we->event) {
|
||||
case SDL_WINDOWEVENT_CLOSE:
|
||||
nf7_util_log_debug("received close request");
|
||||
nf7util_log_debug("received close request");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -12,19 +12,19 @@
|
||||
#include "core/sdl2/mod.h"
|
||||
|
||||
|
||||
struct nf7_core_sdl2_win {
|
||||
struct nf7_core_sdl2* mod;
|
||||
struct nf7_util_malloc* malloc;
|
||||
struct nf7core_sdl2_win {
|
||||
struct nf7core_sdl2* mod;
|
||||
struct nf7util_malloc* malloc;
|
||||
|
||||
SDL_Window* win;
|
||||
uint32_t win_id;
|
||||
void* gl;
|
||||
|
||||
struct nf7_util_signal_recv event_recv;
|
||||
struct nf7util_signal_recv event_recv;
|
||||
|
||||
void* data;
|
||||
void (*handler)(struct nf7_core_sdl2_win*, const SDL_WindowEvent*);
|
||||
void (*handler)(struct nf7core_sdl2_win*, const SDL_WindowEvent*);
|
||||
};
|
||||
|
||||
bool nf7_core_sdl2_win_init(struct nf7_core_sdl2_win*);
|
||||
void nf7_core_sdl2_win_deinit(struct nf7_core_sdl2_win*);
|
||||
bool nf7core_sdl2_win_init(struct nf7core_sdl2_win*);
|
||||
void nf7core_sdl2_win_deinit(struct nf7core_sdl2_win*);
|
||||
|
@ -10,33 +10,33 @@
|
||||
#include "core/sdl2/mod.h"
|
||||
|
||||
|
||||
struct nf7_core_sdl2_win_test {
|
||||
struct nf7_test* test;
|
||||
struct nf7_util_malloc* malloc;
|
||||
struct nf7core_sdl2_win_test {
|
||||
struct nf7test* test;
|
||||
struct nf7util_malloc* malloc;
|
||||
uv_loop_t* uv;
|
||||
|
||||
struct nf7_core_sdl2_win win;
|
||||
struct nf7core_sdl2_win win;
|
||||
uv_timer_t timer;
|
||||
};
|
||||
|
||||
static void finalize_(struct nf7_core_sdl2_win_test*);
|
||||
static void finalize_(struct nf7core_sdl2_win_test*);
|
||||
static void on_time_(uv_timer_t*);
|
||||
static void on_close_(uv_handle_t*);
|
||||
static void on_handle_(struct nf7_core_sdl2_win*, const SDL_WindowEvent*);
|
||||
static void on_handle_(struct nf7core_sdl2_win*, const SDL_WindowEvent*);
|
||||
|
||||
NF7_TEST(nf7_core_sdl2_win_test) {
|
||||
struct nf7_core_sdl2* mod = (void*) nf7_get_mod_by_meta(
|
||||
test_->nf7, (struct nf7_mod_meta*) &nf7_core_sdl2);
|
||||
if (!nf7_test_expect(nullptr != mod)) {
|
||||
NF7TEST(nf7core_sdl2_win_test) {
|
||||
struct nf7core_sdl2* mod = (void*) nf7_get_mod_by_meta(
|
||||
test_->nf7, (struct nf7_mod_meta*) &nf7core_sdl2);
|
||||
if (!nf7test_expect(nullptr != mod)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
struct nf7_core_sdl2_win_test* this =
|
||||
nf7_util_malloc_new(test_->malloc, sizeof(*this));
|
||||
if (!nf7_test_expect(nullptr != this)) {
|
||||
struct nf7core_sdl2_win_test* this =
|
||||
nf7util_malloc_new(test_->malloc, sizeof(*this));
|
||||
if (!nf7test_expect(nullptr != this)) {
|
||||
goto ABORT;
|
||||
}
|
||||
*this = (struct nf7_core_sdl2_win_test) {
|
||||
*this = (struct nf7core_sdl2_win_test) {
|
||||
.test = test_,
|
||||
.malloc = test_->malloc,
|
||||
.uv = test_->nf7->uv,
|
||||
@ -45,20 +45,20 @@ NF7_TEST(nf7_core_sdl2_win_test) {
|
||||
.malloc = test_->malloc,
|
||||
},
|
||||
};
|
||||
nf7_test_ref(this->test);
|
||||
nf7test_ref(this->test);
|
||||
|
||||
if (!nf7_test_expect(nf7_core_sdl2_win_init(&this->win))) {
|
||||
if (!nf7test_expect(nf7core_sdl2_win_init(&this->win))) {
|
||||
goto ABORT;
|
||||
}
|
||||
this->win.data = this;
|
||||
this->win.handler = on_handle_;
|
||||
|
||||
if (0 != nf7_util_log_uv(uv_timer_init(this->uv, &this->timer))) {
|
||||
if (0 != nf7util_log_uv(uv_timer_init(this->uv, &this->timer))) {
|
||||
goto ABORT;
|
||||
}
|
||||
this->timer.data = this;
|
||||
|
||||
if (0 != nf7_util_log_uv(uv_timer_start(&this->timer, on_time_, 3000, 0))) {
|
||||
if (0 != nf7util_log_uv(uv_timer_start(&this->timer, on_time_, 3000, 0))) {
|
||||
goto ABORT;
|
||||
}
|
||||
return true;
|
||||
@ -68,30 +68,30 @@ ABORT:
|
||||
return false;
|
||||
}
|
||||
|
||||
static void finalize_(struct nf7_core_sdl2_win_test* this) {
|
||||
static void finalize_(struct nf7core_sdl2_win_test* this) {
|
||||
if (nullptr != this->timer.data) {
|
||||
nf7_util_log_uv_assert(uv_timer_stop(&this->timer));
|
||||
nf7util_log_uv_assert(uv_timer_stop(&this->timer));
|
||||
uv_close((uv_handle_t*) &this->timer, on_close_);
|
||||
return;
|
||||
}
|
||||
nf7_core_sdl2_win_deinit(&this->win);
|
||||
nf7_test_unref(this->test);
|
||||
nf7_util_malloc_del(this->malloc, this);
|
||||
nf7core_sdl2_win_deinit(&this->win);
|
||||
nf7test_unref(this->test);
|
||||
nf7util_malloc_del(this->malloc, this);
|
||||
}
|
||||
|
||||
static void on_time_(uv_timer_t* timer) {
|
||||
struct nf7_core_sdl2_win_test* this = timer->data;
|
||||
struct nf7core_sdl2_win_test* this = timer->data;
|
||||
finalize_(this);
|
||||
}
|
||||
|
||||
static void on_close_(uv_handle_t* handle) {
|
||||
struct nf7_core_sdl2_win_test* this = handle->data;
|
||||
struct nf7core_sdl2_win_test* this = handle->data;
|
||||
handle->data = nullptr;
|
||||
finalize_(this);
|
||||
}
|
||||
|
||||
static void on_handle_(struct nf7_core_sdl2_win* win, const SDL_WindowEvent* e) {
|
||||
struct nf7_core_sdl2_win_test* this = win->data;
|
||||
static void on_handle_(struct nf7core_sdl2_win* win, const SDL_WindowEvent* e) {
|
||||
struct nf7core_sdl2_win_test* this = win->data;
|
||||
|
||||
switch (e->event) {
|
||||
case SDL_WINDOWEVENT_CLOSE:
|
||||
|
@ -14,38 +14,38 @@
|
||||
static void del_(struct nf7_mod*);
|
||||
|
||||
|
||||
struct nf7_mod* nf7_core_test_new(struct nf7* nf7) {
|
||||
struct nf7_mod* nf7core_test_new(const struct nf7* nf7) {
|
||||
assert(nullptr != nf7);
|
||||
|
||||
struct nf7_core_test* this = nf7_util_malloc_new(nf7->malloc, sizeof(*this));
|
||||
struct nf7core_test* this = nf7util_malloc_new(nf7->malloc, sizeof(*this));
|
||||
if (nullptr == this) {
|
||||
nf7_util_log_error("failed to allocate instance");
|
||||
nf7util_log_error("failed to allocate instance");
|
||||
return nullptr;
|
||||
}
|
||||
*this = (struct nf7_core_test) {
|
||||
.meta = &nf7_core_test,
|
||||
*this = (struct nf7core_test) {
|
||||
.meta = &nf7core_test,
|
||||
.nf7 = nf7,
|
||||
.malloc = nf7->malloc,
|
||||
.uv = nf7->uv,
|
||||
};
|
||||
|
||||
if (!run_trigger_setup_(this)) {
|
||||
nf7_util_log_error("failed to setup runner");
|
||||
nf7util_log_error("failed to setup runner");
|
||||
return nullptr;
|
||||
}
|
||||
return (struct nf7_mod*) this;
|
||||
}
|
||||
|
||||
static void del_(struct nf7_mod* mod) {
|
||||
struct nf7_core_test* this = (struct nf7_core_test*) mod;
|
||||
nf7_util_malloc_del(this->malloc, this);
|
||||
struct nf7core_test* this = (struct nf7core_test*) mod;
|
||||
nf7util_malloc_del(this->malloc, this);
|
||||
}
|
||||
|
||||
|
||||
const struct nf7_mod_meta nf7_core_test = {
|
||||
const struct nf7_mod_meta nf7core_test = {
|
||||
.name = (const uint8_t*) "nf7core_test",
|
||||
.desc = (const uint8_t*) "executes tests after the initialization",
|
||||
.ver = 0,
|
||||
.ver = NF7_VERSION,
|
||||
|
||||
.delete = del_,
|
||||
};
|
||||
|
@ -6,17 +6,17 @@
|
||||
#include "test/common.h"
|
||||
|
||||
|
||||
struct nf7_core_test;
|
||||
struct nf7_core_test_run;
|
||||
struct nf7core_test;
|
||||
struct nf7core_test_run;
|
||||
|
||||
struct nf7_core_test {
|
||||
struct nf7core_test {
|
||||
const struct nf7_mod_meta* meta;
|
||||
|
||||
struct nf7* nf7;
|
||||
struct nf7_util_malloc* malloc;
|
||||
uv_loop_t* uv;
|
||||
const struct nf7* nf7;
|
||||
struct nf7util_malloc* malloc;
|
||||
uv_loop_t* uv;
|
||||
|
||||
struct nf7_core_test_run* run;
|
||||
struct nf7core_test_run* run;
|
||||
};
|
||||
|
||||
extern const struct nf7_mod_meta nf7_core_test;
|
||||
extern const struct nf7_mod_meta nf7core_test;
|
||||
|
@ -13,23 +13,23 @@
|
||||
#include "core/test/mod.h"
|
||||
|
||||
|
||||
static bool run_trigger_setup_(struct nf7_core_test*);
|
||||
static void run_cancel_(struct nf7_core_test_run*);
|
||||
static bool run_trigger_setup_(struct nf7core_test*);
|
||||
static void run_cancel_(struct nf7core_test_run*);
|
||||
static void run_cancel_close_(uv_handle_t*);
|
||||
static void run_trigger_(uv_idle_t*);
|
||||
|
||||
static void run_single_test_(struct nf7_test*, const char*, nf7_test_func);
|
||||
static void run_expect_(struct nf7_test*, bool, const char*);
|
||||
static void run_finalize_(struct nf7_test*);
|
||||
static void run_single_test_(struct nf7test*, const char*, nf7test_func);
|
||||
static void run_expect_(struct nf7test*, bool, const char*);
|
||||
static void run_finalize_(struct nf7test*);
|
||||
|
||||
|
||||
struct nf7_core_test_run {
|
||||
struct nf7_core_test* mod;
|
||||
struct nf7_util_malloc* malloc;
|
||||
struct nf7core_test_run {
|
||||
struct nf7core_test* mod;
|
||||
struct nf7util_malloc* malloc;
|
||||
uv_loop_t* uv;
|
||||
|
||||
uv_idle_t idle;
|
||||
struct nf7_test test;
|
||||
struct nf7test test;
|
||||
|
||||
uint64_t run_tests;
|
||||
uint64_t succeeded_tests;
|
||||
@ -38,15 +38,15 @@ struct nf7_core_test_run {
|
||||
};
|
||||
|
||||
|
||||
static bool run_trigger_setup_(struct nf7_core_test* mod) {
|
||||
static bool run_trigger_setup_(struct nf7core_test* mod) {
|
||||
assert(nullptr != mod);
|
||||
|
||||
struct nf7_core_test_run* this = nf7_util_malloc_new(mod->malloc, sizeof(*this));
|
||||
struct nf7core_test_run* this = nf7util_malloc_new(mod->malloc, sizeof(*this));
|
||||
if (nullptr == this) {
|
||||
nf7_util_log_error("failed to allocate an test context");
|
||||
nf7util_log_error("failed to allocate an test context");
|
||||
return false;
|
||||
}
|
||||
*this = (struct nf7_core_test_run) {
|
||||
*this = (struct nf7core_test_run) {
|
||||
.mod = mod,
|
||||
.malloc = mod->malloc,
|
||||
.uv = mod->uv,
|
||||
@ -59,17 +59,17 @@ static bool run_trigger_setup_(struct nf7_core_test* mod) {
|
||||
.finalize = run_finalize_,
|
||||
},
|
||||
};
|
||||
nf7_test_ref(&this->test);
|
||||
nf7test_ref(&this->test);
|
||||
|
||||
nf7_util_log_uv_assert(uv_idle_init(this->uv, &this->idle));
|
||||
nf7util_log_uv_assert(uv_idle_init(this->uv, &this->idle));
|
||||
this->idle.data = this;
|
||||
nf7_util_log_uv_assert(uv_idle_start(&this->idle, run_trigger_));
|
||||
nf7util_log_uv_assert(uv_idle_start(&this->idle, run_trigger_));
|
||||
|
||||
mod->run = this;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void run_cancel_(struct nf7_core_test_run* this) {
|
||||
static void run_cancel_(struct nf7core_test_run* this) {
|
||||
if (nullptr != this) {
|
||||
if (nullptr != this->mod) {
|
||||
this->mod->run = nullptr;
|
||||
@ -79,30 +79,30 @@ static void run_cancel_(struct nf7_core_test_run* this) {
|
||||
}
|
||||
}
|
||||
static void run_cancel_close_(uv_handle_t* handle) {
|
||||
struct nf7_core_test_run* this = handle->data;
|
||||
nf7_test_unref(&this->test);
|
||||
struct nf7core_test_run* this = handle->data;
|
||||
nf7test_unref(&this->test);
|
||||
}
|
||||
|
||||
static void run_trigger_(uv_idle_t* idle) {
|
||||
struct nf7_core_test_run* this = idle->data;
|
||||
struct nf7core_test_run* this = idle->data;
|
||||
|
||||
nf7_util_log_info("triggering tests...");
|
||||
nf7_test_run(&this->test);
|
||||
nf7_util_log_info("all tests are triggered");
|
||||
nf7util_log_info("triggering tests...");
|
||||
nf7test_run(&this->test);
|
||||
nf7util_log_info("all tests are triggered");
|
||||
|
||||
run_cancel_(this);
|
||||
}
|
||||
|
||||
|
||||
static void run_single_test_(
|
||||
struct nf7_test* test, const char* name, nf7_test_func func) {
|
||||
struct nf7test* test, const char* name, nf7test_func func) {
|
||||
assert(nullptr != test);
|
||||
assert(nullptr != name);
|
||||
assert(nullptr != func);
|
||||
|
||||
struct nf7_core_test_run* this = test->data;
|
||||
struct nf7core_test_run* this = test->data;
|
||||
|
||||
nf7_util_log_info("running test: %s", name);
|
||||
nf7util_log_info("running test: %s", name);
|
||||
|
||||
this->running_test_name = name;
|
||||
const bool result = func(&this->test);
|
||||
@ -111,36 +111,36 @@ static void run_single_test_(
|
||||
++this->run_tests;
|
||||
if (result) {
|
||||
++this->succeeded_tests;
|
||||
nf7_util_log_info("test succeeded: %s", name);
|
||||
nf7util_log_info("test succeeded: %s", name);
|
||||
} else {
|
||||
nf7_util_log_error("TEST FAILED: %s", name);
|
||||
nf7util_log_error("TEST FAILED: %s", name);
|
||||
}
|
||||
}
|
||||
static void run_expect_(struct nf7_test* test, bool val, const char* expr) {
|
||||
static void run_expect_(struct nf7test* test, bool val, const char* expr) {
|
||||
assert(nullptr != test);
|
||||
assert(nullptr != expr);
|
||||
|
||||
if (val) {
|
||||
nf7_util_log_debug("expectation is met: %s", expr);
|
||||
nf7util_log_debug("expectation is met: %s", expr);
|
||||
} else {
|
||||
nf7_util_log_error("expectation is NOT met: %s", expr);
|
||||
nf7util_log_error("expectation is NOT met: %s", expr);
|
||||
}
|
||||
}
|
||||
static void run_finalize_(struct nf7_test* test) {
|
||||
static void run_finalize_(struct nf7test* test) {
|
||||
assert(nullptr != test);
|
||||
|
||||
struct nf7_core_test_run* this = test->data;
|
||||
struct nf7core_test_run* this = test->data;
|
||||
if (0 < this->run_tests) {
|
||||
if (this->succeeded_tests == this->run_tests) {
|
||||
nf7_util_log_info(
|
||||
nf7util_log_info(
|
||||
"all tests (%" PRIu64 ") has passed! :)",
|
||||
this->run_tests);
|
||||
} else {
|
||||
nf7_util_log_warn(
|
||||
nf7util_log_warn(
|
||||
"%" PRIu64 "/%" PRIu64 " tests have FAILED! X(",
|
||||
this->run_tests - this->succeeded_tests,
|
||||
this->run_tests);
|
||||
}
|
||||
}
|
||||
nf7_util_malloc_del(this->malloc, this);
|
||||
nf7util_malloc_del(this->malloc, this);
|
||||
}
|
||||
|
36
main.c
36
main.c
@ -19,13 +19,13 @@ static void cb_close_all_handles_(uv_handle_t*, void*);
|
||||
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
nf7_util_log_info("HELLO :)");
|
||||
struct nf7_util_malloc malloc = {0};
|
||||
nf7util_log_info("HELLO :)");
|
||||
struct nf7util_malloc malloc = {0};
|
||||
|
||||
// init loop
|
||||
uv_loop_t uv;
|
||||
if (0 != nf7_util_log_uv(uv_loop_init(&uv))) {
|
||||
nf7_util_log_error("failed to init main loop");
|
||||
if (0 != nf7util_log_uv(uv_loop_init(&uv))) {
|
||||
nf7util_log_error("failed to init main loop");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
struct nf7 nf7 = {
|
||||
@ -37,51 +37,51 @@ int main(int argc, char** argv) {
|
||||
};
|
||||
|
||||
// load modules
|
||||
struct nf7_mod* nf7_mods[NF7_CORE_MAX_MODS];
|
||||
nf7.mods.n = nf7_core_new(&nf7, nf7_mods);
|
||||
struct nf7mod* nf7_mods[NF7CORE_MAX_MODS];
|
||||
nf7.mods.n = nf7core_new(&nf7, nf7_mods);
|
||||
nf7.mods.ptr = nf7_mods;
|
||||
nf7_util_log_info("loaded %" PRIu32 " modules", nf7.mods.n);
|
||||
nf7util_log_info("loaded %" PRIu32 " modules", nf7.mods.n);
|
||||
|
||||
// main loop
|
||||
if (0 != nf7_util_log_uv(uv_run(&uv, UV_RUN_DEFAULT))) {
|
||||
nf7_util_log_error("failed to start main loop");
|
||||
if (0 != nf7util_log_uv(uv_run(&uv, UV_RUN_DEFAULT))) {
|
||||
nf7util_log_error("failed to start main loop");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
nf7_util_log_info("exiting Nf7...");
|
||||
nf7util_log_info("exiting Nf7...");
|
||||
|
||||
// destroy modules
|
||||
for (uint32_t i = 0; i < nf7.mods.n; ++i) {
|
||||
struct nf7_mod* mod = nf7.mods.ptr[i];
|
||||
assert(mod->meta->delete);
|
||||
|
||||
nf7_util_log_debug("unloading module: %s", mod->meta->name);
|
||||
nf7util_log_debug("unloading module: %s", mod->meta->name);
|
||||
mod->meta->delete(mod);
|
||||
}
|
||||
nf7_util_log_info("unloaded all modules");
|
||||
nf7util_log_info("unloaded all modules");
|
||||
|
||||
// teardown loop
|
||||
uv_walk(&uv, cb_close_all_handles_, nullptr);
|
||||
uv_run(&uv, UV_RUN_DEFAULT);
|
||||
if (0 != uv_loop_close(&uv)) {
|
||||
nf7_util_log_warn("failed to close main loop gracefully");
|
||||
nf7util_log_warn("failed to close main loop gracefully");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
const uint64_t leaks = nf7_util_malloc_get_count(&malloc);
|
||||
const uint64_t leaks = nf7util_malloc_get_count(&malloc);
|
||||
if (0 < leaks) {
|
||||
nf7_util_log_warn("%" PRIu64 " memory leaks detected", leaks);
|
||||
nf7util_log_warn("%" PRIu64 " memory leaks detected", leaks);
|
||||
}
|
||||
|
||||
nf7_util_log_info("ALL DONE X)");
|
||||
nf7util_log_info("ALL DONE X)");
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static void cb_close_all_handles_(uv_handle_t* handle, void*) {
|
||||
const char* name = uv_handle_type_name(handle->type);
|
||||
if (!uv_is_closing(handle)) {
|
||||
nf7_util_log_debug("closing remaining handle: %s", name);
|
||||
nf7util_log_debug("closing remaining handle: %s", name);
|
||||
uv_close(handle, nullptr);
|
||||
} else {
|
||||
nf7_util_log_debug("remaining handle is closing itself: %s", name);
|
||||
nf7util_log_debug("remaining handle is closing itself: %s", name);
|
||||
}
|
||||
}
|
||||
|
6
nf7.h
6
nf7.h
@ -8,6 +8,8 @@
|
||||
#include "util/malloc.h"
|
||||
|
||||
|
||||
#define NF7_VERSION UINT32_C(0)
|
||||
|
||||
struct nf7;
|
||||
struct nf7_mod;
|
||||
struct nf7_mod_meta;
|
||||
@ -19,8 +21,8 @@ struct nf7 {
|
||||
uint32_t argc;
|
||||
const char* const* argv;
|
||||
|
||||
uv_loop_t* uv;
|
||||
struct nf7_util_malloc* malloc;
|
||||
uv_loop_t* uv;
|
||||
struct nf7util_malloc* malloc;
|
||||
|
||||
struct {
|
||||
uint32_t n;
|
||||
|
@ -4,39 +4,39 @@
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
#define NF7_TEST(name) bool name([[maybe_unused]] struct nf7_test* test_)
|
||||
#define NF7TEST(name) bool name([[maybe_unused]] struct nf7test* test_)
|
||||
|
||||
struct nf7;
|
||||
struct nf7_test;
|
||||
struct nf7_util_malloc;
|
||||
struct nf7test;
|
||||
struct nf7util_malloc;
|
||||
|
||||
typedef bool (*nf7_test_func)(struct nf7_test*);
|
||||
typedef bool (*nf7test_func)(struct nf7test*);
|
||||
|
||||
struct nf7_test {
|
||||
struct nf7* nf7;
|
||||
struct nf7_util_malloc* malloc;
|
||||
void* data;
|
||||
struct nf7test {
|
||||
const struct nf7* nf7;
|
||||
struct nf7util_malloc* malloc;
|
||||
void* data;
|
||||
|
||||
uint64_t refcnt;
|
||||
|
||||
void (*run)(struct nf7_test*, const char* name, nf7_test_func);
|
||||
void (*expect)(struct nf7_test*, bool val, const char* expr);
|
||||
void (*finalize)(struct nf7_test*);
|
||||
void (*run)(struct nf7test*, const char* name, nf7test_func);
|
||||
void (*expect)(struct nf7test*, bool val, const char* expr);
|
||||
void (*finalize)(struct nf7test*);
|
||||
};
|
||||
|
||||
|
||||
static inline void nf7_test_ref(struct nf7_test* test) {
|
||||
static inline void nf7test_ref(struct nf7test* test) {
|
||||
++test->refcnt;
|
||||
}
|
||||
static inline void nf7_test_unref(struct nf7_test* test) {
|
||||
static inline void nf7test_unref(struct nf7test* test) {
|
||||
if (--test->refcnt == 0) {
|
||||
test->finalize(test);
|
||||
}
|
||||
}
|
||||
|
||||
#define nf7_test_expect(expr) nf7_test_expect_(test_, (expr), #expr)
|
||||
static inline bool nf7_test_expect_(
|
||||
struct nf7_test* test, bool val, const char* expr) {
|
||||
#define nf7test_expect(expr) nf7test_expect_(test_, (expr), #expr)
|
||||
static inline bool nf7test_expect_(
|
||||
struct nf7test* test, bool val, const char* expr) {
|
||||
test->expect(test, val, expr);
|
||||
return val;
|
||||
}
|
||||
|
@ -1,15 +1,15 @@
|
||||
#!/bin/bash
|
||||
|
||||
tests=$(cat ${@//;/ } | sed -e '/^NF7_TEST(/!d; s|^NF7_TEST(\([^)]*\)).*$|\1|' | xargs echo)
|
||||
tests=$(cat ${@//;/ } | sed -e '/^NF7TEST(/!d; s|^NF7TEST(\([^)]*\)).*$|\1|' | xargs echo)
|
||||
|
||||
echo "#include \"test/common.h\""
|
||||
echo "#include \"test/run.h\""
|
||||
echo
|
||||
echo
|
||||
echo "bool nf7_test_run(struct nf7_test* test) {"
|
||||
echo "bool nf7test_run(struct nf7test* test) {"
|
||||
echo " // $tests"
|
||||
for test in $tests; do
|
||||
echo " extern bool $test(struct nf7_test*);"
|
||||
echo " extern bool $test(struct nf7test*);"
|
||||
echo " test->run(test, \"$test\", $test);"
|
||||
done
|
||||
echo " return true;"
|
||||
|
@ -4,4 +4,4 @@
|
||||
#include "test/common.h"
|
||||
|
||||
|
||||
bool nf7_test_run(struct nf7_test*);
|
||||
bool nf7test_run(struct nf7test*);
|
||||
|
9
thirdparty/CMakeLists.txt
vendored
9
thirdparty/CMakeLists.txt
vendored
@ -9,6 +9,15 @@ FetchContent_Declare(
|
||||
)
|
||||
FetchContent_MakeAvailable(libuv)
|
||||
|
||||
# ---- LuaJIT (MIT)
|
||||
FetchContent_Declare(
|
||||
luajit
|
||||
GIT_REPOSITORY https://github.com/LuaJIT/LuaJIT.git
|
||||
GIT_TAG 8635cbabf3094c4d8bd00578c7d812bea87bb2d3
|
||||
)
|
||||
FetchContent_Populate(luajit)
|
||||
include(luajit.cmake)
|
||||
|
||||
# ---- OpenGL
|
||||
find_package(OpenGL REQUIRED GLOBAL)
|
||||
add_library(OpenGL ALIAS OpenGL::GL)
|
||||
|
56
thirdparty/luajit.cmake
vendored
Normal file
56
thirdparty/luajit.cmake
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
set(src "${luajit_SOURCE_DIR}/src")
|
||||
if (UNIX)
|
||||
find_program(MAKE make REQUIRED)
|
||||
|
||||
set(lib "${src}/libluajit.a")
|
||||
add_custom_target(luajit-build
|
||||
COMMAND
|
||||
${MAKE} -j BUILDMODE=static CFLAGS=-fPIC CXX=${CMAKE_CXX_COMPILER} CC=${CMAKE_C_COMPILER}
|
||||
|
||||
WORKING_DIRECTORY "${luajit_SOURCE_DIR}"
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
# To enable assertions, add the following options:
|
||||
# XCFLAGS="-DLUA_USE_APICHECK -DLUA_USE_ASSERT -Og -g"
|
||||
|
||||
elseif (MINGW)
|
||||
find_program(MAKE mingw32-make REQUIRED)
|
||||
|
||||
set(lib "${src}/libluajit.a")
|
||||
add_custom_target(luajit-build
|
||||
COMMAND ${MAKE} -j BUILDMODE=static CFLAGS=-fPIC
|
||||
|
||||
WORKING_DIRECTORY "${luajit_SOURCE_DIR}/src"
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
elseif (MSVC)
|
||||
set(lib "${src}/lua51.lib")
|
||||
add_custom_command(
|
||||
OUTPUT "${lib}"
|
||||
COMMAND msvcbuild.bat static
|
||||
DEPENDS "${luajit_BINARY_DIR}/skip_build"
|
||||
|
||||
WORKING_DIRECTORY "${src}"
|
||||
VERBATIM
|
||||
)
|
||||
add_custom_target(luajit-build SOURCES "${lib}")
|
||||
|
||||
else()
|
||||
message(ERROR "unknown environment")
|
||||
endif()
|
||||
|
||||
add_library(luajit-imported STATIC IMPORTED)
|
||||
set_target_properties(luajit-imported PROPERTIES
|
||||
IMPORTED_LOCATION "${lib}"
|
||||
)
|
||||
add_dependencies(luajit-imported luajit-build)
|
||||
|
||||
add_library(luajit INTERFACE)
|
||||
target_link_libraries(luajit
|
||||
INTERFACE luajit-imported $<$<PLATFORM_ID:Linux>:m>
|
||||
)
|
||||
target_include_directories(luajit SYSTEM BEFORE
|
||||
INTERFACE "${src}"
|
||||
)
|
68
util/array.h
68
util/array.h
@ -14,29 +14,29 @@
|
||||
//
|
||||
// When you need an array of integers, the following array structs are
|
||||
// available:
|
||||
// - nf7_util_array_u8 / nf7_util_array_s8
|
||||
// - nf7_util_array_u16 / nf7_util_array_s16
|
||||
// - nf7_util_array_u32 / nf7_util_array_s32
|
||||
// - nf7_util_array_u64 / nf7_util_array_s64
|
||||
// - nf7util_array_u8 / nf7util_array_s8
|
||||
// - nf7util_array_u16 / nf7util_array_s16
|
||||
// - nf7util_array_u32 / nf7util_array_s32
|
||||
// - nf7util_array_u64 / nf7util_array_s64
|
||||
//
|
||||
// When you need an array of any other types, expand NF7_UTIL_ARRAY macro on
|
||||
// When you need an array of any other types, expand NF7UTIL_ARRAY macro on
|
||||
// your *.h like this:
|
||||
// `NF7_UTIL_ARRAY(my_array, struct A);`
|
||||
// In addition, expand `NF7_UTIL_ARRAY_IMPL` macro on your *.c like this:
|
||||
// `NF7_UTIL_ARRAY_IMPL(, my_array, struct A);`
|
||||
// `NF7UTIL_ARRAY(my_array, struct A);`
|
||||
// In addition, expand `NF7UTIL_ARRAY_IMPL` macro on your *.c like this:
|
||||
// `NF7UTIL_ARRAY_IMPL(, my_array, struct A);`
|
||||
// After that, `struct my_array` can be used as an array struct.
|
||||
//
|
||||
// If you need the functions be inline, expand NF7_UTIL_ARRAY_INLINE macro on
|
||||
// your *.h as same as NF7_UTIL_ARRAY but NF7_UTIL_ARRAY_IMPL is unnecessary.
|
||||
// If you need the functions be inline, expand NF7UTIL_ARRAY_INLINE macro on
|
||||
// your *.h as same as NF7UTIL_ARRAY but NF7UTIL_ARRAY_IMPL is unnecessary.
|
||||
//
|
||||
// You can see declarations of the functions on a definition of
|
||||
// NF7_UTIL_ARRAY_DECL macro. They all are prefixed by a name of your array
|
||||
// NF7UTIL_ARRAY_DECL macro. They all are prefixed by a name of your array
|
||||
// struct.
|
||||
|
||||
|
||||
#define NF7_UTIL_ARRAY_TYPE(PREFIX, T) \
|
||||
#define NF7UTIL_ARRAY_TYPE(PREFIX, T) \
|
||||
struct PREFIX { \
|
||||
struct nf7_util_malloc* malloc; \
|
||||
struct nf7util_malloc* malloc; \
|
||||
\
|
||||
uint64_t n; \
|
||||
T* ptr; \
|
||||
@ -44,8 +44,8 @@
|
||||
static_assert(true)
|
||||
|
||||
|
||||
#define NF7_UTIL_ARRAY_DECL(ATTR, PREFIX, T) \
|
||||
ATTR void PREFIX##_init(struct PREFIX*, struct nf7_util_malloc*); \
|
||||
#define NF7UTIL_ARRAY_DECL(ATTR, PREFIX, T) \
|
||||
ATTR void PREFIX##_init(struct PREFIX*, struct nf7util_malloc*); \
|
||||
ATTR void PREFIX##_deinit(struct PREFIX*); \
|
||||
ATTR bool PREFIX##_resize(struct PREFIX*, uint64_t); \
|
||||
ATTR bool PREFIX##_insert(struct PREFIX*, uint64_t, T); \
|
||||
@ -55,8 +55,8 @@
|
||||
static_assert(true)
|
||||
|
||||
|
||||
#define NF7_UTIL_ARRAY_IMPL(ATTR, PREFIX, T) \
|
||||
ATTR void PREFIX##_init(struct PREFIX* this, struct nf7_util_malloc* malloc) { \
|
||||
#define NF7UTIL_ARRAY_IMPL(ATTR, PREFIX, T) \
|
||||
ATTR void PREFIX##_init(struct PREFIX* this, struct nf7util_malloc* malloc) { \
|
||||
assert(nullptr != this); \
|
||||
assert(nullptr != malloc); \
|
||||
*this = (struct PREFIX) { \
|
||||
@ -65,7 +65,7 @@
|
||||
} \
|
||||
ATTR void PREFIX##_deinit(struct PREFIX* this) { \
|
||||
assert(nullptr != this); \
|
||||
nf7_util_malloc_del(this->malloc, this->ptr); \
|
||||
nf7util_malloc_del(this->malloc, this->ptr); \
|
||||
*this = (struct PREFIX) {0}; \
|
||||
} \
|
||||
\
|
||||
@ -78,7 +78,7 @@
|
||||
const bool extend = this->n < n; \
|
||||
\
|
||||
T* const newptr = \
|
||||
nf7_util_malloc_renew(this->malloc, this->ptr, n*sizeof(T)); \
|
||||
nf7util_malloc_renew(this->malloc, this->ptr, n*sizeof(T)); \
|
||||
if (0 < n && nullptr == newptr) { \
|
||||
if (extend) { return false; } \
|
||||
} else { \
|
||||
@ -146,23 +146,23 @@
|
||||
static_assert(true)
|
||||
|
||||
|
||||
#define NF7_UTIL_ARRAY(PREFIX, T) \
|
||||
NF7_UTIL_ARRAY_TYPE(PREFIX, T); \
|
||||
NF7_UTIL_ARRAY_DECL(, PREFIX, T); \
|
||||
#define NF7UTIL_ARRAY(PREFIX, T) \
|
||||
NF7UTIL_ARRAY_TYPE(PREFIX, T); \
|
||||
NF7UTIL_ARRAY_DECL(, PREFIX, T); \
|
||||
static_assert(true)
|
||||
|
||||
#define NF7_UTIL_ARRAY_INLINE(PREFIX, T) \
|
||||
NF7_UTIL_ARRAY_TYPE(PREFIX, T); \
|
||||
NF7_UTIL_ARRAY_DECL(static inline, PREFIX, T); \
|
||||
NF7_UTIL_ARRAY_IMPL(static inline, PREFIX, T); \
|
||||
#define NF7UTIL_ARRAY_INLINE(PREFIX, T) \
|
||||
NF7UTIL_ARRAY_TYPE(PREFIX, T); \
|
||||
NF7UTIL_ARRAY_DECL(static inline, PREFIX, T); \
|
||||
NF7UTIL_ARRAY_IMPL(static inline, PREFIX, T); \
|
||||
static_assert(true)
|
||||
|
||||
|
||||
NF7_UTIL_ARRAY_INLINE(nf7_util_array_u8 , uint8_t);
|
||||
NF7_UTIL_ARRAY_INLINE(nf7_util_array_u16, uint16_t);
|
||||
NF7_UTIL_ARRAY_INLINE(nf7_util_array_u32, uint32_t);
|
||||
NF7_UTIL_ARRAY_INLINE(nf7_util_array_u64, uint64_t);
|
||||
NF7_UTIL_ARRAY_INLINE(nf7_util_array_s8 , int8_t);
|
||||
NF7_UTIL_ARRAY_INLINE(nf7_util_array_s16, int16_t);
|
||||
NF7_UTIL_ARRAY_INLINE(nf7_util_array_s32, int32_t);
|
||||
NF7_UTIL_ARRAY_INLINE(nf7_util_array_s64, int64_t);
|
||||
NF7UTIL_ARRAY_INLINE(nf7util_array_u8 , uint8_t);
|
||||
NF7UTIL_ARRAY_INLINE(nf7util_array_u16, uint16_t);
|
||||
NF7UTIL_ARRAY_INLINE(nf7util_array_u32, uint32_t);
|
||||
NF7UTIL_ARRAY_INLINE(nf7util_array_u64, uint64_t);
|
||||
NF7UTIL_ARRAY_INLINE(nf7util_array_s8 , int8_t);
|
||||
NF7UTIL_ARRAY_INLINE(nf7util_array_s16, int16_t);
|
||||
NF7UTIL_ARRAY_INLINE(nf7util_array_s32, int32_t);
|
||||
NF7UTIL_ARRAY_INLINE(nf7util_array_s64, int64_t);
|
||||
|
@ -7,225 +7,225 @@
|
||||
|
||||
|
||||
#define TEST_(T) do { \
|
||||
struct nf7_util_array_##T sut; \
|
||||
nf7_util_array_##T##_init(&sut, test_->malloc); \
|
||||
struct nf7util_array_##T sut; \
|
||||
nf7util_array_##T##_init(&sut, test_->malloc); \
|
||||
const bool ret = \
|
||||
nf7_test_expect(nf7_util_array_##T##_resize(&sut, 32)) && \
|
||||
nf7_test_expect(32 == sut.n); \
|
||||
nf7_util_array_##T##_deinit(&sut); \
|
||||
nf7test_expect(nf7util_array_##T##_resize(&sut, 32)) && \
|
||||
nf7test_expect(32 == sut.n); \
|
||||
nf7util_array_##T##_deinit(&sut); \
|
||||
return ret; \
|
||||
} while (0)
|
||||
NF7_TEST(nf7_util_array_u8_test_resize) { TEST_(u8); }
|
||||
NF7_TEST(nf7_util_array_u16_test_resize) { TEST_(u16); }
|
||||
NF7_TEST(nf7_util_array_u32_test_resize) { TEST_(u32); }
|
||||
NF7_TEST(nf7_util_array_u64_test_resize) { TEST_(u64); }
|
||||
NF7_TEST(nf7_util_array_s8_test_resize) { TEST_(s8); }
|
||||
NF7_TEST(nf7_util_array_s16_test_resize) { TEST_(s16); }
|
||||
NF7_TEST(nf7_util_array_s32_test_resize) { TEST_(s32); }
|
||||
NF7_TEST(nf7_util_array_s64_test_resize) { TEST_(s64); }
|
||||
NF7TEST(nf7util_array_u8_test_resize) { TEST_(u8); }
|
||||
NF7TEST(nf7util_array_u16_test_resize) { TEST_(u16); }
|
||||
NF7TEST(nf7util_array_u32_test_resize) { TEST_(u32); }
|
||||
NF7TEST(nf7util_array_u64_test_resize) { TEST_(u64); }
|
||||
NF7TEST(nf7util_array_s8_test_resize) { TEST_(s8); }
|
||||
NF7TEST(nf7util_array_s16_test_resize) { TEST_(s16); }
|
||||
NF7TEST(nf7util_array_s32_test_resize) { TEST_(s32); }
|
||||
NF7TEST(nf7util_array_s64_test_resize) { TEST_(s64); }
|
||||
#undef TEST_
|
||||
|
||||
#define TEST_(T) do { \
|
||||
struct nf7_util_array_##T sut; \
|
||||
nf7_util_array_##T##_init(&sut, test_->malloc); \
|
||||
struct nf7util_array_##T sut; \
|
||||
nf7util_array_##T##_init(&sut, test_->malloc); \
|
||||
const bool ret = \
|
||||
nf7_test_expect(nf7_util_array_##T##_insert(&sut, 0, 66)) && \
|
||||
nf7_test_expect(1 == sut.n); \
|
||||
nf7_test_expect(66 == sut.ptr[0]); \
|
||||
nf7_util_array_##T##_deinit(&sut); \
|
||||
nf7test_expect(nf7util_array_##T##_insert(&sut, 0, 66)) && \
|
||||
nf7test_expect(1 == sut.n); \
|
||||
nf7test_expect(66 == sut.ptr[0]); \
|
||||
nf7util_array_##T##_deinit(&sut); \
|
||||
return ret; \
|
||||
} while (0)
|
||||
NF7_TEST(nf7_util_array_u8_test_insert_first) { TEST_(u8); }
|
||||
NF7_TEST(nf7_util_array_u16_test_insert_first) { TEST_(u16); }
|
||||
NF7_TEST(nf7_util_array_u32_test_insert_first) { TEST_(u32); }
|
||||
NF7_TEST(nf7_util_array_u64_test_insert_first) { TEST_(u64); }
|
||||
NF7_TEST(nf7_util_array_s8_test_insert_first) { TEST_(s8); }
|
||||
NF7_TEST(nf7_util_array_s16_test_insert_first) { TEST_(s16); }
|
||||
NF7_TEST(nf7_util_array_s32_test_insert_first) { TEST_(s32); }
|
||||
NF7_TEST(nf7_util_array_s64_test_insert_first) { TEST_(s64); }
|
||||
NF7TEST(nf7util_array_u8_test_insert_first) { TEST_(u8); }
|
||||
NF7TEST(nf7util_array_u16_test_insert_first) { TEST_(u16); }
|
||||
NF7TEST(nf7util_array_u32_test_insert_first) { TEST_(u32); }
|
||||
NF7TEST(nf7util_array_u64_test_insert_first) { TEST_(u64); }
|
||||
NF7TEST(nf7util_array_s8_test_insert_first) { TEST_(s8); }
|
||||
NF7TEST(nf7util_array_s16_test_insert_first) { TEST_(s16); }
|
||||
NF7TEST(nf7util_array_s32_test_insert_first) { TEST_(s32); }
|
||||
NF7TEST(nf7util_array_s64_test_insert_first) { TEST_(s64); }
|
||||
#undef TEST_
|
||||
|
||||
#define TEST_(T) do { \
|
||||
struct nf7_util_array_##T sut; \
|
||||
nf7_util_array_##T##_init(&sut, test_->malloc); \
|
||||
struct nf7util_array_##T sut; \
|
||||
nf7util_array_##T##_init(&sut, test_->malloc); \
|
||||
const bool ret = \
|
||||
nf7_test_expect(nf7_util_array_##T##_insert(&sut, 0, 66)) && \
|
||||
nf7_test_expect(nf7_util_array_##T##_insert(&sut, 0, 77)) && \
|
||||
nf7_test_expect(2 == sut.n) && \
|
||||
nf7_test_expect(77 == sut.ptr[0]) && \
|
||||
nf7_test_expect(66 == sut.ptr[1]); \
|
||||
nf7_util_array_##T##_deinit(&sut); \
|
||||
nf7test_expect(nf7util_array_##T##_insert(&sut, 0, 66)) && \
|
||||
nf7test_expect(nf7util_array_##T##_insert(&sut, 0, 77)) && \
|
||||
nf7test_expect(2 == sut.n) && \
|
||||
nf7test_expect(77 == sut.ptr[0]) && \
|
||||
nf7test_expect(66 == sut.ptr[1]); \
|
||||
nf7util_array_##T##_deinit(&sut); \
|
||||
return ret; \
|
||||
} while (0)
|
||||
NF7_TEST(nf7_util_array_u8_test_insert_head) { TEST_(u8); }
|
||||
NF7_TEST(nf7_util_array_u16_test_insert_head) { TEST_(u16); }
|
||||
NF7_TEST(nf7_util_array_u32_test_insert_head) { TEST_(u32); }
|
||||
NF7_TEST(nf7_util_array_u64_test_insert_head) { TEST_(u64); }
|
||||
NF7_TEST(nf7_util_array_s8_test_insert_head) { TEST_(s8); }
|
||||
NF7_TEST(nf7_util_array_s16_test_insert_head) { TEST_(s16); }
|
||||
NF7_TEST(nf7_util_array_s32_test_insert_head) { TEST_(s32); }
|
||||
NF7_TEST(nf7_util_array_s64_test_insert_head) { TEST_(s64); }
|
||||
NF7TEST(nf7util_array_u8_test_insert_head) { TEST_(u8); }
|
||||
NF7TEST(nf7util_array_u16_test_insert_head) { TEST_(u16); }
|
||||
NF7TEST(nf7util_array_u32_test_insert_head) { TEST_(u32); }
|
||||
NF7TEST(nf7util_array_u64_test_insert_head) { TEST_(u64); }
|
||||
NF7TEST(nf7util_array_s8_test_insert_head) { TEST_(s8); }
|
||||
NF7TEST(nf7util_array_s16_test_insert_head) { TEST_(s16); }
|
||||
NF7TEST(nf7util_array_s32_test_insert_head) { TEST_(s32); }
|
||||
NF7TEST(nf7util_array_s64_test_insert_head) { TEST_(s64); }
|
||||
#undef TEST_
|
||||
|
||||
#define TEST_(T) do { \
|
||||
struct nf7_util_array_##T sut; \
|
||||
nf7_util_array_##T##_init(&sut, test_->malloc); \
|
||||
struct nf7util_array_##T sut; \
|
||||
nf7util_array_##T##_init(&sut, test_->malloc); \
|
||||
const bool ret = \
|
||||
nf7_test_expect(nf7_util_array_##T##_insert(&sut, UINT64_MAX, 66)) && \
|
||||
nf7_test_expect(nf7_util_array_##T##_insert(&sut, UINT64_MAX, 77)) && \
|
||||
nf7_test_expect(2 == sut.n) && \
|
||||
nf7_test_expect(66 == sut.ptr[0]) && \
|
||||
nf7_test_expect(77 == sut.ptr[1]); \
|
||||
nf7_util_array_##T##_deinit(&sut); \
|
||||
nf7test_expect(nf7util_array_##T##_insert(&sut, UINT64_MAX, 66)) && \
|
||||
nf7test_expect(nf7util_array_##T##_insert(&sut, UINT64_MAX, 77)) && \
|
||||
nf7test_expect(2 == sut.n) && \
|
||||
nf7test_expect(66 == sut.ptr[0]) && \
|
||||
nf7test_expect(77 == sut.ptr[1]); \
|
||||
nf7util_array_##T##_deinit(&sut); \
|
||||
return ret; \
|
||||
} while (0)
|
||||
NF7_TEST(nf7_util_array_u8_test_insert_tail) { TEST_(u8); }
|
||||
NF7_TEST(nf7_util_array_u16_test_insert_tail) { TEST_(u16); }
|
||||
NF7_TEST(nf7_util_array_u32_test_insert_tail) { TEST_(u32); }
|
||||
NF7_TEST(nf7_util_array_u64_test_insert_tail) { TEST_(u64); }
|
||||
NF7_TEST(nf7_util_array_s8_test_insert_tail) { TEST_(s8); }
|
||||
NF7_TEST(nf7_util_array_s16_test_insert_tail) { TEST_(s16); }
|
||||
NF7_TEST(nf7_util_array_s32_test_insert_tail) { TEST_(s32); }
|
||||
NF7_TEST(nf7_util_array_s64_test_insert_tail) { TEST_(s64); }
|
||||
NF7TEST(nf7util_array_u8_test_insert_tail) { TEST_(u8); }
|
||||
NF7TEST(nf7util_array_u16_test_insert_tail) { TEST_(u16); }
|
||||
NF7TEST(nf7util_array_u32_test_insert_tail) { TEST_(u32); }
|
||||
NF7TEST(nf7util_array_u64_test_insert_tail) { TEST_(u64); }
|
||||
NF7TEST(nf7util_array_s8_test_insert_tail) { TEST_(s8); }
|
||||
NF7TEST(nf7util_array_s16_test_insert_tail) { TEST_(s16); }
|
||||
NF7TEST(nf7util_array_s32_test_insert_tail) { TEST_(s32); }
|
||||
NF7TEST(nf7util_array_s64_test_insert_tail) { TEST_(s64); }
|
||||
#undef TEST_
|
||||
|
||||
#define TEST_(T) do { \
|
||||
struct nf7_util_array_##T sut; \
|
||||
nf7_util_array_##T##_init(&sut, test_->malloc); \
|
||||
struct nf7util_array_##T sut; \
|
||||
nf7util_array_##T##_init(&sut, test_->malloc); \
|
||||
const bool ret = \
|
||||
nf7_test_expect(nf7_util_array_##T##_insert(&sut, UINT64_MAX, 66)) && \
|
||||
nf7_test_expect(nf7_util_array_##T##_insert(&sut, UINT64_MAX, 88)) && \
|
||||
nf7_test_expect(nf7_util_array_##T##_insert(&sut, 1, 77)) && \
|
||||
nf7_test_expect(3 == sut.n) && \
|
||||
nf7_test_expect(66 == sut.ptr[0]) && \
|
||||
nf7_test_expect(77 == sut.ptr[1]) && \
|
||||
nf7_test_expect(88 == sut.ptr[2]); \
|
||||
nf7_util_array_##T##_deinit(&sut); \
|
||||
nf7test_expect(nf7util_array_##T##_insert(&sut, UINT64_MAX, 66)) && \
|
||||
nf7test_expect(nf7util_array_##T##_insert(&sut, UINT64_MAX, 88)) && \
|
||||
nf7test_expect(nf7util_array_##T##_insert(&sut, 1, 77)) && \
|
||||
nf7test_expect(3 == sut.n) && \
|
||||
nf7test_expect(66 == sut.ptr[0]) && \
|
||||
nf7test_expect(77 == sut.ptr[1]) && \
|
||||
nf7test_expect(88 == sut.ptr[2]); \
|
||||
nf7util_array_##T##_deinit(&sut); \
|
||||
return ret; \
|
||||
} while (0)
|
||||
NF7_TEST(nf7_util_array_u8_test_insert_mid) { TEST_(u8); }
|
||||
NF7_TEST(nf7_util_array_u16_test_insert_mid) { TEST_(u16); }
|
||||
NF7_TEST(nf7_util_array_u32_test_insert_mid) { TEST_(u32); }
|
||||
NF7_TEST(nf7_util_array_u64_test_insert_mid) { TEST_(u64); }
|
||||
NF7_TEST(nf7_util_array_s8_test_insert_mid) { TEST_(s8); }
|
||||
NF7_TEST(nf7_util_array_s16_test_insert_mid) { TEST_(s16); }
|
||||
NF7_TEST(nf7_util_array_s32_test_insert_mid) { TEST_(s32); }
|
||||
NF7_TEST(nf7_util_array_s64_test_insert_mid) { TEST_(s64); }
|
||||
NF7TEST(nf7util_array_u8_test_insert_mid) { TEST_(u8); }
|
||||
NF7TEST(nf7util_array_u16_test_insert_mid) { TEST_(u16); }
|
||||
NF7TEST(nf7util_array_u32_test_insert_mid) { TEST_(u32); }
|
||||
NF7TEST(nf7util_array_u64_test_insert_mid) { TEST_(u64); }
|
||||
NF7TEST(nf7util_array_s8_test_insert_mid) { TEST_(s8); }
|
||||
NF7TEST(nf7util_array_s16_test_insert_mid) { TEST_(s16); }
|
||||
NF7TEST(nf7util_array_s32_test_insert_mid) { TEST_(s32); }
|
||||
NF7TEST(nf7util_array_s64_test_insert_mid) { TEST_(s64); }
|
||||
#undef TEST_
|
||||
|
||||
#define TEST_(T) do { \
|
||||
struct nf7_util_array_##T sut; \
|
||||
nf7_util_array_##T##_init(&sut, test_->malloc); \
|
||||
struct nf7util_array_##T sut; \
|
||||
nf7util_array_##T##_init(&sut, test_->malloc); \
|
||||
const bool ret = \
|
||||
nf7_test_expect(nf7_util_array_##T##_insert(&sut, UINT64_MAX, 66)) && \
|
||||
nf7_test_expect(nf7_util_array_##T##_insert(&sut, UINT64_MAX, 77)) && \
|
||||
nf7_test_expect(nf7_util_array_##T##_insert(&sut, UINT64_MAX, 88)) && \
|
||||
(nf7_util_array_##T##_remove(&sut, 0), true) && \
|
||||
nf7_test_expect(2 == sut.n) && \
|
||||
nf7_test_expect(77 == sut.ptr[0]) && \
|
||||
nf7_test_expect(88 == sut.ptr[1]); \
|
||||
nf7_util_array_##T##_deinit(&sut); \
|
||||
nf7test_expect(nf7util_array_##T##_insert(&sut, UINT64_MAX, 66)) && \
|
||||
nf7test_expect(nf7util_array_##T##_insert(&sut, UINT64_MAX, 77)) && \
|
||||
nf7test_expect(nf7util_array_##T##_insert(&sut, UINT64_MAX, 88)) && \
|
||||
(nf7util_array_##T##_remove(&sut, 0), true) && \
|
||||
nf7test_expect(2 == sut.n) && \
|
||||
nf7test_expect(77 == sut.ptr[0]) && \
|
||||
nf7test_expect(88 == sut.ptr[1]); \
|
||||
nf7util_array_##T##_deinit(&sut); \
|
||||
return ret; \
|
||||
} while (0)
|
||||
NF7_TEST(nf7_util_array_u8_test_remove_head) { TEST_(u8); }
|
||||
NF7_TEST(nf7_util_array_u16_test_remove_head) { TEST_(u16); }
|
||||
NF7_TEST(nf7_util_array_u32_test_remove_head) { TEST_(u32); }
|
||||
NF7_TEST(nf7_util_array_u64_test_remove_head) { TEST_(u64); }
|
||||
NF7_TEST(nf7_util_array_s8_test_remove_head) { TEST_(s8); }
|
||||
NF7_TEST(nf7_util_array_s16_test_remove_head) { TEST_(s16); }
|
||||
NF7_TEST(nf7_util_array_s32_test_remove_head) { TEST_(s32); }
|
||||
NF7_TEST(nf7_util_array_s64_test_remove_head) { TEST_(s64); }
|
||||
NF7TEST(nf7util_array_u8_test_remove_head) { TEST_(u8); }
|
||||
NF7TEST(nf7util_array_u16_test_remove_head) { TEST_(u16); }
|
||||
NF7TEST(nf7util_array_u32_test_remove_head) { TEST_(u32); }
|
||||
NF7TEST(nf7util_array_u64_test_remove_head) { TEST_(u64); }
|
||||
NF7TEST(nf7util_array_s8_test_remove_head) { TEST_(s8); }
|
||||
NF7TEST(nf7util_array_s16_test_remove_head) { TEST_(s16); }
|
||||
NF7TEST(nf7util_array_s32_test_remove_head) { TEST_(s32); }
|
||||
NF7TEST(nf7util_array_s64_test_remove_head) { TEST_(s64); }
|
||||
#undef TEST_
|
||||
|
||||
#define TEST_(T) do { \
|
||||
struct nf7_util_array_##T sut; \
|
||||
nf7_util_array_##T##_init(&sut, test_->malloc); \
|
||||
struct nf7util_array_##T sut; \
|
||||
nf7util_array_##T##_init(&sut, test_->malloc); \
|
||||
const bool ret = \
|
||||
nf7_test_expect(nf7_util_array_##T##_insert(&sut, UINT64_MAX, 66)) && \
|
||||
nf7_test_expect(nf7_util_array_##T##_insert(&sut, UINT64_MAX, 77)) && \
|
||||
nf7_test_expect(nf7_util_array_##T##_insert(&sut, UINT64_MAX, 88)) && \
|
||||
(nf7_util_array_##T##_remove(&sut, UINT64_MAX), true) && \
|
||||
nf7_test_expect(2 == sut.n) && \
|
||||
nf7_test_expect(66 == sut.ptr[0]) && \
|
||||
nf7_test_expect(77 == sut.ptr[1]); \
|
||||
nf7_util_array_##T##_deinit(&sut); \
|
||||
nf7test_expect(nf7util_array_##T##_insert(&sut, UINT64_MAX, 66)) && \
|
||||
nf7test_expect(nf7util_array_##T##_insert(&sut, UINT64_MAX, 77)) && \
|
||||
nf7test_expect(nf7util_array_##T##_insert(&sut, UINT64_MAX, 88)) && \
|
||||
(nf7util_array_##T##_remove(&sut, UINT64_MAX), true) && \
|
||||
nf7test_expect(2 == sut.n) && \
|
||||
nf7test_expect(66 == sut.ptr[0]) && \
|
||||
nf7test_expect(77 == sut.ptr[1]); \
|
||||
nf7util_array_##T##_deinit(&sut); \
|
||||
return ret; \
|
||||
} while (0)
|
||||
NF7_TEST(nf7_util_array_u8_test_remove_tail) { TEST_(u8); }
|
||||
NF7_TEST(nf7_util_array_u16_test_remove_tail) { TEST_(u16); }
|
||||
NF7_TEST(nf7_util_array_u32_test_remove_tail) { TEST_(u32); }
|
||||
NF7_TEST(nf7_util_array_u64_test_remove_tail) { TEST_(u64); }
|
||||
NF7_TEST(nf7_util_array_s8_test_remove_tail) { TEST_(s8); }
|
||||
NF7_TEST(nf7_util_array_s16_test_remove_tail) { TEST_(s16); }
|
||||
NF7_TEST(nf7_util_array_s32_test_remove_tail) { TEST_(s32); }
|
||||
NF7_TEST(nf7_util_array_s64_test_remove_tail) { TEST_(s64); }
|
||||
NF7TEST(nf7util_array_u8_test_remove_tail) { TEST_(u8); }
|
||||
NF7TEST(nf7util_array_u16_test_remove_tail) { TEST_(u16); }
|
||||
NF7TEST(nf7util_array_u32_test_remove_tail) { TEST_(u32); }
|
||||
NF7TEST(nf7util_array_u64_test_remove_tail) { TEST_(u64); }
|
||||
NF7TEST(nf7util_array_s8_test_remove_tail) { TEST_(s8); }
|
||||
NF7TEST(nf7util_array_s16_test_remove_tail) { TEST_(s16); }
|
||||
NF7TEST(nf7util_array_s32_test_remove_tail) { TEST_(s32); }
|
||||
NF7TEST(nf7util_array_s64_test_remove_tail) { TEST_(s64); }
|
||||
#undef TEST_
|
||||
|
||||
#define TEST_(T) do { \
|
||||
struct nf7_util_array_##T sut; \
|
||||
nf7_util_array_##T##_init(&sut, test_->malloc); \
|
||||
struct nf7util_array_##T sut; \
|
||||
nf7util_array_##T##_init(&sut, test_->malloc); \
|
||||
const bool ret = \
|
||||
nf7_test_expect(nf7_util_array_##T##_insert(&sut, UINT64_MAX, 66)) && \
|
||||
nf7_test_expect(nf7_util_array_##T##_insert(&sut, UINT64_MAX, 77)) && \
|
||||
nf7_test_expect(nf7_util_array_##T##_insert(&sut, UINT64_MAX, 88)) && \
|
||||
(nf7_util_array_##T##_remove(&sut, 1), true) && \
|
||||
nf7_test_expect(2 == sut.n) && \
|
||||
nf7_test_expect(66 == sut.ptr[0]) && \
|
||||
nf7_test_expect(88 == sut.ptr[1]); \
|
||||
nf7_util_array_##T##_deinit(&sut); \
|
||||
nf7test_expect(nf7util_array_##T##_insert(&sut, UINT64_MAX, 66)) && \
|
||||
nf7test_expect(nf7util_array_##T##_insert(&sut, UINT64_MAX, 77)) && \
|
||||
nf7test_expect(nf7util_array_##T##_insert(&sut, UINT64_MAX, 88)) && \
|
||||
(nf7util_array_##T##_remove(&sut, 1), true) && \
|
||||
nf7test_expect(2 == sut.n) && \
|
||||
nf7test_expect(66 == sut.ptr[0]) && \
|
||||
nf7test_expect(88 == sut.ptr[1]); \
|
||||
nf7util_array_##T##_deinit(&sut); \
|
||||
return ret; \
|
||||
} while (0)
|
||||
NF7_TEST(nf7_util_array_u8_test_remove_mid) { TEST_(u8); }
|
||||
NF7_TEST(nf7_util_array_u16_test_remove_mid) { TEST_(u16); }
|
||||
NF7_TEST(nf7_util_array_u32_test_remove_mid) { TEST_(u32); }
|
||||
NF7_TEST(nf7_util_array_u64_test_remove_mid) { TEST_(u64); }
|
||||
NF7_TEST(nf7_util_array_s8_test_remove_mid) { TEST_(s8); }
|
||||
NF7_TEST(nf7_util_array_s16_test_remove_mid) { TEST_(s16); }
|
||||
NF7_TEST(nf7_util_array_s32_test_remove_mid) { TEST_(s32); }
|
||||
NF7_TEST(nf7_util_array_s64_test_remove_mid) { TEST_(s64); }
|
||||
NF7TEST(nf7util_array_u8_test_remove_mid) { TEST_(u8); }
|
||||
NF7TEST(nf7util_array_u16_test_remove_mid) { TEST_(u16); }
|
||||
NF7TEST(nf7util_array_u32_test_remove_mid) { TEST_(u32); }
|
||||
NF7TEST(nf7util_array_u64_test_remove_mid) { TEST_(u64); }
|
||||
NF7TEST(nf7util_array_s8_test_remove_mid) { TEST_(s8); }
|
||||
NF7TEST(nf7util_array_s16_test_remove_mid) { TEST_(s16); }
|
||||
NF7TEST(nf7util_array_s32_test_remove_mid) { TEST_(s32); }
|
||||
NF7TEST(nf7util_array_s64_test_remove_mid) { TEST_(s64); }
|
||||
#undef TEST_
|
||||
|
||||
#define TEST_(T) do { \
|
||||
struct nf7_util_array_##T sut; \
|
||||
nf7_util_array_##T##_init(&sut, test_->malloc); \
|
||||
struct nf7util_array_##T sut; \
|
||||
nf7util_array_##T##_init(&sut, test_->malloc); \
|
||||
uint64_t idx; \
|
||||
const bool ret = \
|
||||
nf7_test_expect(nf7_util_array_##T##_insert(&sut, UINT64_MAX, 66)) && \
|
||||
nf7_test_expect(nf7_util_array_##T##_insert(&sut, UINT64_MAX, 77)) && \
|
||||
nf7_test_expect(nf7_util_array_##T##_insert(&sut, UINT64_MAX, 88)) && \
|
||||
nf7_test_expect(nf7_util_array_##T##_find(&sut, &idx, 77)) && \
|
||||
nf7_test_expect(1 == idx); \
|
||||
nf7_util_array_##T##_deinit(&sut); \
|
||||
nf7test_expect(nf7util_array_##T##_insert(&sut, UINT64_MAX, 66)) && \
|
||||
nf7test_expect(nf7util_array_##T##_insert(&sut, UINT64_MAX, 77)) && \
|
||||
nf7test_expect(nf7util_array_##T##_insert(&sut, UINT64_MAX, 88)) && \
|
||||
nf7test_expect(nf7util_array_##T##_find(&sut, &idx, 77)) && \
|
||||
nf7test_expect(1 == idx); \
|
||||
nf7util_array_##T##_deinit(&sut); \
|
||||
return ret; \
|
||||
} while (0)
|
||||
NF7_TEST(nf7_util_array_u8_test_find_found) { TEST_(u8); }
|
||||
NF7_TEST(nf7_util_array_u16_test_find_found) { TEST_(u16); }
|
||||
NF7_TEST(nf7_util_array_u32_test_find_found) { TEST_(u32); }
|
||||
NF7_TEST(nf7_util_array_u64_test_find_found) { TEST_(u64); }
|
||||
NF7_TEST(nf7_util_array_s8_test_find_found) { TEST_(s8); }
|
||||
NF7_TEST(nf7_util_array_s16_test_find_found) { TEST_(s16); }
|
||||
NF7_TEST(nf7_util_array_s32_test_find_found) { TEST_(s32); }
|
||||
NF7_TEST(nf7_util_array_s64_test_find_found) { TEST_(s64); }
|
||||
NF7TEST(nf7util_array_u8_test_find_found) { TEST_(u8); }
|
||||
NF7TEST(nf7util_array_u16_test_find_found) { TEST_(u16); }
|
||||
NF7TEST(nf7util_array_u32_test_find_found) { TEST_(u32); }
|
||||
NF7TEST(nf7util_array_u64_test_find_found) { TEST_(u64); }
|
||||
NF7TEST(nf7util_array_s8_test_find_found) { TEST_(s8); }
|
||||
NF7TEST(nf7util_array_s16_test_find_found) { TEST_(s16); }
|
||||
NF7TEST(nf7util_array_s32_test_find_found) { TEST_(s32); }
|
||||
NF7TEST(nf7util_array_s64_test_find_found) { TEST_(s64); }
|
||||
#undef TEST_
|
||||
|
||||
#define TEST_(T) do { \
|
||||
struct nf7_util_array_##T sut; \
|
||||
nf7_util_array_##T##_init(&sut, test_->malloc); \
|
||||
struct nf7util_array_##T sut; \
|
||||
nf7util_array_##T##_init(&sut, test_->malloc); \
|
||||
uint64_t idx; \
|
||||
const bool ret = \
|
||||
nf7_test_expect(nf7_util_array_##T##_insert(&sut, UINT64_MAX, 66)) && \
|
||||
nf7_test_expect(nf7_util_array_##T##_insert(&sut, UINT64_MAX, 77)) && \
|
||||
nf7_test_expect(nf7_util_array_##T##_insert(&sut, UINT64_MAX, 88)) && \
|
||||
nf7_test_expect(!nf7_util_array_##T##_find(&sut, &idx, 99)); \
|
||||
nf7_util_array_##T##_deinit(&sut); \
|
||||
nf7test_expect(nf7util_array_##T##_insert(&sut, UINT64_MAX, 66)) && \
|
||||
nf7test_expect(nf7util_array_##T##_insert(&sut, UINT64_MAX, 77)) && \
|
||||
nf7test_expect(nf7util_array_##T##_insert(&sut, UINT64_MAX, 88)) && \
|
||||
nf7test_expect(!nf7util_array_##T##_find(&sut, &idx, 99)); \
|
||||
nf7util_array_##T##_deinit(&sut); \
|
||||
return ret; \
|
||||
} while (0)
|
||||
NF7_TEST(nf7_util_array_u8_test_find_notfound) { TEST_(u8); }
|
||||
NF7_TEST(nf7_util_array_u16_test_find_notfound) { TEST_(u16); }
|
||||
NF7_TEST(nf7_util_array_u32_test_find_notfound) { TEST_(u32); }
|
||||
NF7_TEST(nf7_util_array_u64_test_find_notfound) { TEST_(u64); }
|
||||
NF7_TEST(nf7_util_array_s8_test_find_notfound) { TEST_(s8); }
|
||||
NF7_TEST(nf7_util_array_s16_test_find_notfound) { TEST_(s16); }
|
||||
NF7_TEST(nf7_util_array_s32_test_find_notfound) { TEST_(s32); }
|
||||
NF7_TEST(nf7_util_array_s64_test_find_notfound) { TEST_(s64); }
|
||||
NF7TEST(nf7util_array_u8_test_find_notfound) { TEST_(u8); }
|
||||
NF7TEST(nf7util_array_u16_test_find_notfound) { TEST_(u16); }
|
||||
NF7TEST(nf7util_array_u32_test_find_notfound) { TEST_(u32); }
|
||||
NF7TEST(nf7util_array_u64_test_find_notfound) { TEST_(u64); }
|
||||
NF7TEST(nf7util_array_s8_test_find_notfound) { TEST_(s8); }
|
||||
NF7TEST(nf7util_array_s16_test_find_notfound) { TEST_(s16); }
|
||||
NF7TEST(nf7util_array_s32_test_find_notfound) { TEST_(s32); }
|
||||
NF7TEST(nf7util_array_s64_test_find_notfound) { TEST_(s64); }
|
||||
#undef TEST_
|
||||
|
42
util/log.h
42
util/log.h
@ -9,45 +9,45 @@
|
||||
#include <uv.h>
|
||||
|
||||
|
||||
#define NF7_UTIL_LOG_CURRENT_FILE \
|
||||
#define NF7UTIL_LOG_CURRENT_FILE \
|
||||
((const char*) __FILE__ + NF7_PROJECT_DIR_LEN)
|
||||
|
||||
#define nf7_util_log(level, file, line, func, fmt, ...) \
|
||||
#define nf7util_log(level, file, line, func, fmt, ...) \
|
||||
printf(level "|%s:%" PRIu64 "|%s|" fmt "\n", file, (uint64_t) line, func __VA_OPT__(,) __VA_ARGS__)
|
||||
#define nf7_util_log_sugar(level, ...) \
|
||||
nf7_util_log(level, NF7_UTIL_LOG_CURRENT_FILE, __LINE__, __func__, __VA_ARGS__)
|
||||
#define nf7util_log_sugar(level, ...) \
|
||||
nf7util_log(level, NF7UTIL_LOG_CURRENT_FILE, __LINE__, __func__, __VA_ARGS__)
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
# define nf7_util_log_debug(...) \
|
||||
nf7_util_log_sugar("DBG", __VA_ARGS__)
|
||||
# define nf7util_log_debug(...) \
|
||||
nf7util_log_sugar("DBG", __VA_ARGS__)
|
||||
#else
|
||||
# define nf7_util_log_debug(fmt, ...) do { } while (0)
|
||||
# define nf7util_log_debug(fmt, ...) do { } while (0)
|
||||
#endif
|
||||
|
||||
#define nf7_util_log_info(...) \
|
||||
nf7_util_log_sugar("INF", __VA_ARGS__)
|
||||
#define nf7_util_log_warn(...) \
|
||||
nf7_util_log_sugar("WRN", __VA_ARGS__)
|
||||
#define nf7_util_log_error(...) \
|
||||
nf7_util_log_sugar("ERR", __VA_ARGS__)
|
||||
#define nf7util_log_info(...) \
|
||||
nf7util_log_sugar("INF", __VA_ARGS__)
|
||||
#define nf7util_log_warn(...) \
|
||||
nf7util_log_sugar("WRN", __VA_ARGS__)
|
||||
#define nf7util_log_error(...) \
|
||||
nf7util_log_sugar("ERR", __VA_ARGS__)
|
||||
|
||||
|
||||
// ---- libuv utils
|
||||
#define nf7_util_log_uv(ret) \
|
||||
nf7_util_log_uv_((ret), NF7_UTIL_LOG_CURRENT_FILE, __LINE__, __func__)
|
||||
static inline int nf7_util_log_uv_(
|
||||
#define nf7util_log_uv(ret) \
|
||||
nf7util_log_uv_((ret), NF7UTIL_LOG_CURRENT_FILE, __LINE__, __func__)
|
||||
static inline int nf7util_log_uv_(
|
||||
int ret, const char* file, uint64_t line, const char* func) {
|
||||
if (0 != ret) {
|
||||
nf7_util_log("INF", file, line, func, "uv api error: %s", uv_strerror(ret));
|
||||
nf7util_log("INF", file, line, func, "uv api error: %s", uv_strerror(ret));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define nf7_util_log_uv_assert(ret) \
|
||||
nf7_util_log_uv_((ret), NF7_UTIL_LOG_CURRENT_FILE, __LINE__, __func__)
|
||||
static inline int nf7_util_log_uv_assert_(
|
||||
#define nf7util_log_uv_assert(ret) \
|
||||
nf7util_log_uv_((ret), NF7UTIL_LOG_CURRENT_FILE, __LINE__, __func__)
|
||||
static inline int nf7util_log_uv_assert_(
|
||||
int ret, const char* file, uint64_t line, const char* func) {
|
||||
nf7_util_log_uv_(ret, file, line, func);
|
||||
nf7util_log_uv_(ret, file, line, func);
|
||||
assert(0 == ret);
|
||||
return ret;
|
||||
}
|
||||
|
@ -4,14 +4,14 @@
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
void* nf7_util_malloc_stack_new(struct nf7_util_malloc_stack* const this, const uint64_t n) {
|
||||
void* nf7util_malloc_stack_new(struct nf7util_malloc_stack* const this, const uint64_t n) {
|
||||
assert(nullptr != this);
|
||||
|
||||
if (this->end < this->tail + n) {
|
||||
const uint64_t tail = this->tail - this->begin;
|
||||
const uint64_t size = tail + n;
|
||||
|
||||
uint8_t* const ptr = nf7_util_malloc_renew(this->malloc, this->begin, size);
|
||||
uint8_t* const ptr = nf7util_malloc_renew(this->malloc, this->begin, size);
|
||||
if (nullptr == ptr) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -27,7 +27,7 @@ void* nf7_util_malloc_stack_new(struct nf7_util_malloc_stack* const this, const
|
||||
return this->head;
|
||||
}
|
||||
|
||||
void nf7_util_malloc_stack_del(struct nf7_util_malloc_stack* const this, void* const ptr) {
|
||||
void nf7util_malloc_stack_del(struct nf7util_malloc_stack* const this, void* const ptr) {
|
||||
assert(nullptr != this);
|
||||
assert(0 < this->refcnt);
|
||||
|
||||
|
@ -9,9 +9,9 @@
|
||||
|
||||
// ---- General Purpose Memory Allocator
|
||||
// The current implementation is just a wrap of malloc/free.
|
||||
struct nf7_util_malloc { atomic_uint_least64_t count; };
|
||||
struct nf7util_malloc { atomic_uint_least64_t count; };
|
||||
|
||||
static inline void* nf7_util_malloc_new(struct nf7_util_malloc* this, uint64_t n) {
|
||||
static inline void* nf7util_malloc_new(struct nf7util_malloc* this, uint64_t n) {
|
||||
assert(nullptr != this);
|
||||
|
||||
if (0 == n) {
|
||||
@ -27,7 +27,7 @@ static inline void* nf7_util_malloc_new(struct nf7_util_malloc* this, uint64_t n
|
||||
assert(UINT64_MAX > prev_count);
|
||||
return ret;
|
||||
}
|
||||
static inline void nf7_util_malloc_del(struct nf7_util_malloc* this, void* ptr) {
|
||||
static inline void nf7util_malloc_del(struct nf7util_malloc* this, void* ptr) {
|
||||
assert(nullptr != this);
|
||||
|
||||
if (nullptr != ptr) {
|
||||
@ -37,25 +37,25 @@ static inline void nf7_util_malloc_del(struct nf7_util_malloc* this, void* ptr)
|
||||
free(ptr);
|
||||
}
|
||||
}
|
||||
static inline void* nf7_util_malloc_renew(struct nf7_util_malloc* this, void* ptr, uint64_t n) {
|
||||
static inline void* nf7util_malloc_renew(struct nf7util_malloc* this, void* ptr, uint64_t n) {
|
||||
assert(nullptr != this);
|
||||
|
||||
if (n > 0) {
|
||||
return nullptr != ptr? realloc(ptr, n): nf7_util_malloc_new(this, n);
|
||||
return nullptr != ptr? realloc(ptr, n): nf7util_malloc_new(this, n);
|
||||
} else {
|
||||
nf7_util_malloc_del(this, ptr);
|
||||
nf7util_malloc_del(this, ptr);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint64_t nf7_util_malloc_get_count(const struct nf7_util_malloc* this) {
|
||||
static inline uint64_t nf7util_malloc_get_count(const struct nf7util_malloc* this) {
|
||||
return atomic_load(&this->count);
|
||||
}
|
||||
|
||||
|
||||
// ---- Stack Allocator
|
||||
struct nf7_util_malloc_stack {
|
||||
struct nf7_util_malloc* malloc;
|
||||
struct nf7util_malloc_stack {
|
||||
struct nf7util_malloc* malloc;
|
||||
|
||||
uint8_t* begin;
|
||||
uint8_t* end;
|
||||
@ -64,5 +64,5 @@ struct nf7_util_malloc_stack {
|
||||
uint64_t refcnt;
|
||||
};
|
||||
|
||||
void* nf7_util_malloc_stack_new(struct nf7_util_malloc_stack* this, uint64_t n);
|
||||
void nf7_util_malloc_stack_del(struct nf7_util_malloc_stack* this, void*);
|
||||
void* nf7util_malloc_stack_new(struct nf7util_malloc_stack* this, uint64_t n);
|
||||
void nf7util_malloc_stack_del(struct nf7util_malloc_stack* this, void*);
|
||||
|
@ -7,17 +7,19 @@
|
||||
#include "util/malloc.h"
|
||||
|
||||
|
||||
#define NF7_UTIL_REFCNT_DECL(ATTR, T) \
|
||||
#define NF7UTIL_REFCNT_DECL(ATTR, T) \
|
||||
ATTR void T##_ref(struct T*); \
|
||||
ATTR bool T##_unref(struct T*); \
|
||||
static_assert(true)
|
||||
|
||||
|
||||
#define NF7_UTIL_REFCNT_IMPL(ATTR, T, DELETER) \
|
||||
#define NF7UTIL_REFCNT_IMPL(ATTR, T, DELETER) \
|
||||
ATTR void T##_ref(struct T* this) { \
|
||||
assert(nullptr != this); \
|
||||
++this->refcnt; \
|
||||
} \
|
||||
ATTR bool T##_unref(struct T* this) { \
|
||||
assert(nullptr != this); \
|
||||
assert(0 < this->refcnt); \
|
||||
if (0 == --this->refcnt) { \
|
||||
{DELETER}; \
|
||||
@ -27,11 +29,13 @@
|
||||
} \
|
||||
static_assert(true)
|
||||
|
||||
#define NF7_UTIL_REFCNT_IMPL_ATOMIC(ATTR, T, DELETER) \
|
||||
#define NF7UTIL_REFCNT_IMPL_ATOMIC(ATTR, T, DELETER) \
|
||||
ATTR void T##_ref(struct T* this) { \
|
||||
assert(nullptr != this); \
|
||||
atomic_fetch_add(&this->refcnt, 1); \
|
||||
} \
|
||||
ATTR bool T##_unref(struct T* this) { \
|
||||
assert(nullptr != this); \
|
||||
assert(0 < this->refcnt); \
|
||||
if (1 == atomic_fetch_sub(&this->refcnt, 1)) { \
|
||||
{DELETER}; \
|
||||
|
@ -11,33 +11,33 @@ struct mystruct {
|
||||
bool deleted;
|
||||
uint64_t refcnt;
|
||||
};
|
||||
NF7_UTIL_REFCNT_IMPL(static inline, mystruct, {this->deleted = true;});
|
||||
NF7UTIL_REFCNT_IMPL(static inline, mystruct, {this->deleted = true;});
|
||||
|
||||
struct mystruct_atomic {
|
||||
bool deleted;
|
||||
atomic_uint_least64_t refcnt;
|
||||
};
|
||||
NF7_UTIL_REFCNT_IMPL_ATOMIC(static inline, mystruct_atomic, {this->deleted = true;});
|
||||
NF7UTIL_REFCNT_IMPL_ATOMIC(static inline, mystruct_atomic, {this->deleted = true;});
|
||||
|
||||
|
||||
NF7_TEST(nf7_util_refcnt_test_delete) {
|
||||
NF7TEST(nf7util_refcnt_test_delete) {
|
||||
struct mystruct sut = {0};
|
||||
mystruct_ref(&sut);
|
||||
mystruct_ref(&sut);
|
||||
return
|
||||
nf7_test_expect(!mystruct_unref(&sut)) &&
|
||||
nf7_test_expect(!sut.deleted) &&
|
||||
nf7_test_expect(mystruct_unref(&sut)) &&
|
||||
nf7_test_expect(sut.deleted);
|
||||
nf7test_expect(!mystruct_unref(&sut)) &&
|
||||
nf7test_expect(!sut.deleted) &&
|
||||
nf7test_expect(mystruct_unref(&sut)) &&
|
||||
nf7test_expect(sut.deleted);
|
||||
}
|
||||
|
||||
NF7_TEST(nf7_util_refcnt_test_atomic_delete) {
|
||||
NF7TEST(nf7util_refcnt_test_atomic_delete) {
|
||||
struct mystruct_atomic sut = {0};
|
||||
mystruct_atomic_ref(&sut);
|
||||
mystruct_atomic_ref(&sut);
|
||||
return
|
||||
nf7_test_expect(!mystruct_atomic_unref(&sut)) &&
|
||||
nf7_test_expect(!sut.deleted) &&
|
||||
nf7_test_expect(mystruct_atomic_unref(&sut)) &&
|
||||
nf7_test_expect(sut.deleted);
|
||||
nf7test_expect(!mystruct_atomic_unref(&sut)) &&
|
||||
nf7test_expect(!sut.deleted) &&
|
||||
nf7test_expect(mystruct_atomic_unref(&sut)) &&
|
||||
nf7test_expect(sut.deleted);
|
||||
}
|
||||
|
@ -5,65 +5,65 @@
|
||||
#include "util/malloc.h"
|
||||
|
||||
|
||||
struct nf7_util_signal;
|
||||
struct nf7_util_signal_recv;
|
||||
struct nf7util_signal;
|
||||
struct nf7util_signal_recv;
|
||||
|
||||
NF7_UTIL_ARRAY_INLINE(nf7_util_signal_recvs, struct nf7_util_signal_recv*);
|
||||
NF7UTIL_ARRAY_INLINE(nf7util_signal_recvs, struct nf7util_signal_recv*);
|
||||
|
||||
|
||||
struct nf7_util_signal {
|
||||
struct nf7_util_malloc* malloc;
|
||||
struct nf7util_signal {
|
||||
struct nf7util_malloc* malloc;
|
||||
|
||||
bool emitting;
|
||||
struct nf7_util_signal_recvs recvs;
|
||||
struct nf7util_signal_recvs recvs;
|
||||
};
|
||||
|
||||
struct nf7_util_signal_recv {
|
||||
struct nf7_util_signal* signal;
|
||||
struct nf7util_signal_recv {
|
||||
struct nf7util_signal* signal;
|
||||
|
||||
void* data;
|
||||
void (*func)(struct nf7_util_signal_recv*);
|
||||
void (*func)(struct nf7util_signal_recv*);
|
||||
};
|
||||
|
||||
|
||||
static inline void nf7_util_signal_init(struct nf7_util_signal* this) {
|
||||
static inline void nf7util_signal_init(struct nf7util_signal* this) {
|
||||
assert(nullptr != this);
|
||||
assert(nullptr != this->malloc);
|
||||
nf7_util_signal_recvs_init(&this->recvs, this->malloc);
|
||||
nf7util_signal_recvs_init(&this->recvs, this->malloc);
|
||||
}
|
||||
static inline void nf7_util_signal_deinit(struct nf7_util_signal* this) {
|
||||
static inline void nf7util_signal_deinit(struct nf7util_signal* this) {
|
||||
assert(nullptr != this);
|
||||
for (uint64_t i = 0; i < this->recvs.n; ++i) {
|
||||
this->recvs.ptr[i]->signal = nullptr;
|
||||
}
|
||||
nf7_util_signal_recvs_deinit(&this->recvs);
|
||||
nf7util_signal_recvs_deinit(&this->recvs);
|
||||
}
|
||||
static inline void nf7_util_signal_emit(struct nf7_util_signal* this) {
|
||||
static inline void nf7util_signal_emit(struct nf7util_signal* this) {
|
||||
this->emitting = true;
|
||||
for (uint64_t i = 0; i < this->recvs.n; ++i) {
|
||||
struct nf7_util_signal_recv* recv = this->recvs.ptr[i];
|
||||
struct nf7util_signal_recv* recv = this->recvs.ptr[i];
|
||||
recv->func(recv);
|
||||
}
|
||||
this->emitting = false;
|
||||
}
|
||||
|
||||
static inline void nf7_util_signal_recv_unset(struct nf7_util_signal_recv* this) {
|
||||
static inline void nf7util_signal_recv_unset(struct nf7util_signal_recv* this) {
|
||||
assert(nullptr != this);
|
||||
|
||||
if (nullptr == this->signal) {
|
||||
return;
|
||||
}
|
||||
nf7_util_signal_recvs_find_and_remove(&this->signal->recvs, this);
|
||||
nf7util_signal_recvs_find_and_remove(&this->signal->recvs, this);
|
||||
}
|
||||
static inline bool nf7_util_signal_recv_set(
|
||||
struct nf7_util_signal_recv* this, struct nf7_util_signal* signal) {
|
||||
static inline bool nf7util_signal_recv_set(
|
||||
struct nf7util_signal_recv* this, struct nf7util_signal* signal) {
|
||||
assert(nullptr != this);
|
||||
assert(nullptr != this->func);
|
||||
assert(!signal->emitting);
|
||||
|
||||
nf7_util_signal_recv_unset(this);
|
||||
nf7util_signal_recv_unset(this);
|
||||
|
||||
if (!nf7_util_signal_recvs_insert(&signal->recvs, UINT64_MAX, this)) {
|
||||
if (!nf7util_signal_recvs_insert(&signal->recvs, UINT64_MAX, this)) {
|
||||
return false;
|
||||
}
|
||||
this->signal = signal;
|
||||
|
@ -3,73 +3,73 @@
|
||||
|
||||
#include "test/common.h"
|
||||
|
||||
static void on_recv_(struct nf7_util_signal_recv* recv) {
|
||||
static void on_recv_(struct nf7util_signal_recv* recv) {
|
||||
uint32_t* cnt = recv->data;
|
||||
++*cnt;
|
||||
}
|
||||
|
||||
|
||||
NF7_TEST(nf7_util_signal_test_emit) {
|
||||
NF7TEST(nf7util_signal_test_emit) {
|
||||
uint32_t cnt = 0;
|
||||
|
||||
struct nf7_util_signal signal = {
|
||||
struct nf7util_signal signal = {
|
||||
.malloc = test_->malloc,
|
||||
};
|
||||
nf7_util_signal_init(&signal);
|
||||
nf7util_signal_init(&signal);
|
||||
|
||||
struct nf7_util_signal_recv recv = {
|
||||
struct nf7util_signal_recv recv = {
|
||||
.data = &cnt,
|
||||
.func = on_recv_,
|
||||
};
|
||||
nf7_util_signal_recv_set(&recv, &signal);
|
||||
nf7util_signal_recv_set(&recv, &signal);
|
||||
|
||||
nf7_util_signal_emit(&signal);
|
||||
if (!nf7_test_expect(1 == cnt)) {
|
||||
nf7util_signal_emit(&signal);
|
||||
if (!nf7test_expect(1 == cnt)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nf7_util_signal_deinit(&signal);
|
||||
nf7util_signal_deinit(&signal);
|
||||
return true;
|
||||
}
|
||||
|
||||
NF7_TEST(nf7_util_signal_test_emit_after_unset) {
|
||||
NF7TEST(nf7util_signal_test_emit_after_unset) {
|
||||
uint32_t cnt = 0;
|
||||
|
||||
struct nf7_util_signal signal = {
|
||||
struct nf7util_signal signal = {
|
||||
.malloc = test_->malloc,
|
||||
};
|
||||
nf7_util_signal_init(&signal);
|
||||
nf7util_signal_init(&signal);
|
||||
|
||||
struct nf7_util_signal_recv recv = {
|
||||
struct nf7util_signal_recv recv = {
|
||||
.data = &cnt,
|
||||
.func = on_recv_,
|
||||
};
|
||||
nf7_util_signal_recv_set(&recv, &signal);
|
||||
nf7_util_signal_recv_unset(&recv);
|
||||
nf7util_signal_recv_set(&recv, &signal);
|
||||
nf7util_signal_recv_unset(&recv);
|
||||
|
||||
nf7_util_signal_emit(&signal);
|
||||
if (!nf7_test_expect(0 == cnt)) {
|
||||
nf7util_signal_emit(&signal);
|
||||
if (!nf7test_expect(0 == cnt)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nf7_util_signal_deinit(&signal);
|
||||
nf7util_signal_deinit(&signal);
|
||||
return true;
|
||||
}
|
||||
|
||||
NF7_TEST(nf7_util_signal_test_del_after_set) {
|
||||
NF7TEST(nf7util_signal_test_del_after_set) {
|
||||
uint32_t cnt = 0;
|
||||
|
||||
struct nf7_util_signal signal = {
|
||||
struct nf7util_signal signal = {
|
||||
.malloc = test_->malloc,
|
||||
};
|
||||
nf7_util_signal_init(&signal);
|
||||
nf7util_signal_init(&signal);
|
||||
|
||||
struct nf7_util_signal_recv recv = {
|
||||
struct nf7util_signal_recv recv = {
|
||||
.data = &cnt,
|
||||
.func = on_recv_,
|
||||
};
|
||||
nf7_util_signal_recv_set(&recv, &signal);
|
||||
nf7_util_signal_deinit(&signal);
|
||||
nf7util_signal_recv_set(&recv, &signal);
|
||||
nf7util_signal_deinit(&signal);
|
||||
|
||||
return nf7_test_expect(0 == cnt);
|
||||
return nf7test_expect(0 == cnt);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user