enhance Node C API

This commit is contained in:
falsycat 2022-12-21 13:46:53 +09:00
parent 0e50b539e5
commit 87b5e461b8
2 changed files with 132 additions and 45 deletions

View File

@ -29,16 +29,19 @@ typedef struct nf7_vtable_t {
// ---- context methods ----
struct {
void (*emit)(nf7_ctx_t*, const char* name, nf7_value_t*);
void (*emit)(nf7_ctx_t*, const char* name, const nf7_value_t*);
// thread-safe
void (*exec_async)(nf7_ctx_t*, void (*f)(nf7_ctx_t*), uint64_t ms);
void (*exec_sub) (nf7_ctx_t*, void (*f)(nf7_ctx_t*), uint64_t ms);
void (*exec_async)(nf7_ctx_t*, void*, void (*f)(nf7_ctx_t*, void*), uint64_t ms);
void (*exec_emit)(nf7_ctx_t*, const char* name, const nf7_value_t*, uint64_t ms);
} ctx;
// ---- value accessor/mutator ----
struct {
uint8_t (*get_type)(nf7_value_t*);
nf7_value_t* (*create) (const nf7_value_t*);
void (*destroy)(nf7_value_t*);
uint8_t (*get_type)(const nf7_value_t*);
# define NF7_PULSE UINT8_C(0)
# define NF7_BOOLEAN UINT8_C(1)
# define NF7_INTEGER UINT8_C(2)
@ -49,13 +52,12 @@ typedef struct nf7_vtable_t {
# define NF7_UNKNOWN UINT8_MAX
// A result of value_get_type should be checked before calling the followings.
bool* (*get_boolean)(nf7_value_t*);
int64_t* (*get_integer)(nf7_value_t*);
double* (*get_scalar) (nf7_value_t*);
char* (*get_string) (nf7_value_t*, size_t*);
const uint8_t* (*get_vector) (nf7_value_t*, size_t*);
uint8_t* (*get_mvector)(nf7_value_t*, size_t*);
nf7_value_t* (*get_tuple) (nf7_value_t*, const char*);
bool (*get_boolean)(const nf7_value_t*, bool*);
bool (*get_integer)(const nf7_value_t*, int64_t*);
bool (*get_scalar) (const nf7_value_t*, double*);
const char* (*get_string)(const nf7_value_t*, size_t*);
const uint8_t* (*get_vector)(const nf7_value_t*, size_t*);
const nf7_value_t* (*get_tuple) (const nf7_value_t*, const char*);
void (*set_pulse) (nf7_value_t*);
void (*set_boolean)(nf7_value_t*, bool);
@ -63,7 +65,7 @@ typedef struct nf7_vtable_t {
void (*set_scalar) (nf7_value_t*, double);
char* (*set_string) (nf7_value_t*, size_t);
uint8_t* (*set_vector) (nf7_value_t*, size_t);
void (*set_tuple) (nf7_value_t*, const char**, size_t);
void (*set_tuple) (nf7_value_t*, const char**, nf7_value_t**);
} value;
} nf7_vtable_t;

View File

@ -1,3 +1,4 @@
#include <cassert>
#include <filesystem>
#include <memory>
#include <optional>
@ -53,15 +54,48 @@ static const nf7_vtable_t kVtable = {
},
},
.ctx = {
.emit = [](nf7_ctx_t* ptr, const char* name, nf7_value_t* v) {
.emit = [](nf7_ctx_t* ptr, const char* name, const nf7_value_t* v) {
auto& p = *reinterpret_cast<adaptor::Context*>(ptr);
p.caller->Handle(name, *reinterpret_cast<nf7::Value*>(v), p.callee);
p.caller->Handle(name, *reinterpret_cast<const nf7::Value*>(v), p.callee);
},
.exec_async = [](nf7_ctx_t* ptr, void* udata, void (*f)(nf7_ctx_t*, void*), uint64_t ms) {
auto& p = *reinterpret_cast<adaptor::Context*>(ptr);
const auto time = ms?
nf7::Env::Clock::now() + std::chrono::milliseconds(ms):
nf7::Env::Time::min();
p.callee->env().ExecAsync(p.callee, [udata, f, p]() mutable {
nf7::Value temp;
p.base.value = reinterpret_cast<nf7_value_t*>(&temp);
f(&p.base, udata);
}, time);
},
.exec_emit = [](nf7_ctx_t* ptr, const char* n, const nf7_value_t* vptr, uint64_t ms) {
auto& p = *reinterpret_cast<adaptor::Context*>(ptr);
auto name = std::string {n};
auto& v = *reinterpret_cast<const nf7::Value*>(vptr);
const auto time = ms?
nf7::Env::Clock::now() + std::chrono::milliseconds(ms):
nf7::Env::Time::min();
p.callee->env().ExecSub(p.callee, [p, name, v]() mutable {
p.caller->Handle(name, v, p.callee);
}, time);
},
.exec_async = nullptr, // TODO
.exec_sub = nullptr, // TODO
},
.value = {
.get_type = [](nf7_value_t* vptr) {
.create = [](const nf7_value_t* vptr) {
if (vptr) {
const auto& v = *reinterpret_cast<const nf7::Value*>(vptr);
return reinterpret_cast<nf7_value_t*>(new nf7::Value {v});
} else {
return reinterpret_cast<nf7_value_t*>(new nf7::Value {});
}
},
.destroy = [](nf7_value_t* vptr) {
delete reinterpret_cast<nf7::Value*>(vptr);
},
.get_type = [](const nf7_value_t* vptr) {
struct Visitor {
uint8_t operator()(nf7::Value::Pulse) { return NF7_PULSE; }
uint8_t operator()(nf7::Value::Boolean) { return NF7_BOOLEAN; }
@ -72,43 +106,94 @@ static const nf7_vtable_t kVtable = {
uint8_t operator()(const nf7::Value::ConstTuple&) { return NF7_TUPLE; }
uint8_t operator()(const nf7::Value::DataPtr&) { return NF7_UNKNOWN; }
};
const auto& v = *reinterpret_cast<nf7::Value*>(vptr);
const auto& v = *reinterpret_cast<const nf7::Value*>(vptr);
return std::visit(Visitor {}, v.value());
},
.get_boolean = [](nf7_value_t* vptr) {
auto& v = *reinterpret_cast<nf7::Value*>(vptr);
return v.isBoolean()? &v.boolean(): nullptr;
.get_boolean = [](const nf7_value_t* vptr, bool* ret) {
auto& v = *reinterpret_cast<const nf7::Value*>(vptr);
if (!v.isBoolean()) return false;
*ret = v.boolean();
return true;
},
.get_integer = [](nf7_value_t* vptr) {
auto& v = *reinterpret_cast<nf7::Value*>(vptr);
return v.isInteger()? &v.integer(): nullptr;
.get_integer = [](const nf7_value_t* vptr, int64_t* ret) {
auto& v = *reinterpret_cast<const nf7::Value*>(vptr);
if (!v.isInteger()) return false;
*ret = v.integer();
return true;
},
.get_scalar = [](nf7_value_t* vptr) {
auto& v = *reinterpret_cast<nf7::Value*>(vptr);
return v.isScalar()? &v.scalar(): nullptr;
.get_scalar = [](const nf7_value_t* vptr, double* ret) {
auto& v = *reinterpret_cast<const nf7::Value*>(vptr);
if (!v.isScalar()) return false;
*ret = v.scalar();
return true;
},
.get_string = [](nf7_value_t* vptr, size_t* n) -> char* {
auto& v = *reinterpret_cast<nf7::Value*>(vptr);
if (v.isString()) {
auto& str = v.string();
*n = str.size();
return str.data();
} else {
.get_string = [](const nf7_value_t* vptr, size_t* n) -> const char* {
auto& v = *reinterpret_cast<const nf7::Value*>(vptr);
if (!v.isString()) return nullptr;
auto& str = v.string();
if (n) *n = str.size();
return str.data();
},
.get_vector = [](const nf7_value_t* vptr, size_t* n) -> const uint8_t* {
auto& v = *reinterpret_cast<const nf7::Value*>(vptr);
if (!v.isVector()) return nullptr;
auto& vec = v.vector();
*n = vec->size();
return vec->data();
},
.get_tuple = [](const nf7_value_t* vptr, const char* name) -> const nf7_value_t* {
auto& v = *reinterpret_cast<const nf7::Value*>(vptr);
try {
return reinterpret_cast<const nf7_value_t*>(&v.tuple(name));
} catch (nf7::Exception&) {
return nullptr;
}
},
// TODO
.get_vector = nullptr,
.get_mvector = nullptr,
.get_tuple = nullptr,
.set_pulse = nullptr,
.set_boolean = nullptr,
.set_integer = nullptr,
.set_scalar = nullptr,
.set_string = nullptr,
.set_vector = nullptr,
.set_tuple = nullptr,
.set_pulse = [](nf7_value_t* vptr) {
auto& v = *reinterpret_cast<nf7::Value*>(vptr);
v = nf7::Value::Pulse {};
},
.set_boolean = [](nf7_value_t* vptr, nf7::Value::Boolean b) {
auto& v = *reinterpret_cast<nf7::Value*>(vptr);
v = b;
},
.set_integer = [](nf7_value_t* vptr, nf7::Value::Integer i) {
auto& v = *reinterpret_cast<nf7::Value*>(vptr);
v = i;
},
.set_scalar = [](nf7_value_t* vptr, nf7::Value::Scalar s) {
auto& v = *reinterpret_cast<nf7::Value*>(vptr);
v = s;
},
.set_string = [](nf7_value_t* vptr, size_t n) {
auto& v = *reinterpret_cast<nf7::Value*>(vptr);
v = nf7::Value::String(n, ' ');
return v.string().data();
},
.set_vector = [](nf7_value_t* vptr, size_t n) {
auto& v = *reinterpret_cast<nf7::Value*>(vptr);
auto vec = std::vector<uint8_t>(n);
auto ret = vec.data();
v = std::move(vec);
assert(v.vector()->data() == ret);
return ret;
},
.set_tuple = [](nf7_value_t* vptr, const char** names, nf7_value_t** ret) {
const char** itr = names;
while (*itr) ++itr;
const auto n = static_cast<size_t>(itr-names);
std::vector<nf7::Value::TuplePair> ps;
ps.reserve(n);
for (size_t i = 0; i < n; ++i) {
ps.emplace_back(names[i], nf7::Value {});
ret[i] = reinterpret_cast<nf7_value_t*>(&ps.back().second);
}
auto& v = *reinterpret_cast<nf7::Value*>(vptr);
v = std::move(ps);
},
},
};