From cf1917f00d28381023d2e30f767adc5872b21084 Mon Sep 17 00:00:00 2001 From: Loïc Collignon Date: Wed, 2 Jan 2019 17:44:27 +0100 Subject: c++: New C++ API for bindings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit You can implement a C++ binding API by inheriting the templated base class 'base_api_t' and overriding the methods you want. At the same time, the c++ files are now located in in their own subdirectory: afb/c++ Change-Id: Ie02535961ec6b4b5ae21390cb520acb1fdc44c9e Signed-off-by: Loïc Collignon --- include/afb/afb-binding | 3 +- include/afb/afb-binding.hpp | 692 ------------------------------------- include/afb/c++/binding | 19 + include/afb/c++/binding-object.hpp | 323 +++++++++++++++++ include/afb/c++/binding-wrap.hpp | 692 +++++++++++++++++++++++++++++++++++++ 5 files changed, 1036 insertions(+), 693 deletions(-) delete mode 100644 include/afb/afb-binding.hpp create mode 100644 include/afb/c++/binding create mode 100644 include/afb/c++/binding-object.hpp create mode 100644 include/afb/c++/binding-wrap.hpp diff --git a/include/afb/afb-binding b/include/afb/afb-binding index 96d2ec9c..a961a408 100644 --- a/include/afb/afb-binding +++ b/include/afb/afb-binding @@ -15,5 +15,6 @@ * limitations under the License. */ #pragma once -#include "afb-binding.hpp" +#include "c++/binding-wrap.hpp" +#include "c++/binding-object.hpp" diff --git a/include/afb/afb-binding.hpp b/include/afb/afb-binding.hpp deleted file mode 100644 index 0cb64423..00000000 --- a/include/afb/afb-binding.hpp +++ /dev/null @@ -1,692 +0,0 @@ -/* - * Copyright (C) 2016-2019 "IoT.bzh" - * Author: José Bollo - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include -#include -#include -#include - -/* ensure version */ -#ifndef AFB_BINDING_VERSION -# define AFB_BINDING_VERSION 3 -#endif - -/* check the version */ -#if AFB_BINDING_VERSION < 2 -# error "AFB_BINDING_VERSION must be at least 2 but 3 is prefered" -#endif - -/* get C definitions of bindings */ -extern "C" { -#include "afb-binding.h" -} - -namespace afb { -/*************************************************************************/ -/* pre-declaration of classes */ -/*************************************************************************/ - -class arg; -class event; -class req; - -/*************************************************************************/ -/* declaration of functions */ -/*************************************************************************/ - -int broadcast_event(const char *name, json_object *object = nullptr); - -event make_event(const char *name); - -void verbose(int level, const char *file, int line, const char * func, const char *fmt, va_list args); - -void verbose(int level, const char *file, int line, const char * func, const char *fmt, ...); - -int rootdir_get_fd(); - -int rootdir_open_locale_fd(const char *filename, int flags, const char *locale = nullptr); - -int queue_job(void (*callback)(int signum, void *arg), void *argument, void *group, int timeout); - -int require_api(const char *apiname, bool initialized = true); - -int add_alias(const char *apiname, const char *aliasname); - -int verbosity(); - -bool wants_errors(); -bool wants_warnings(); -bool wants_notices(); -bool wants_infos(); -bool wants_debugs(); - -#if AFB_BINDING_VERSION >= 3 -void call(const char *api, const char *verb, struct json_object *args, void (*callback)(void*closure, int iserror, struct json_object *result, afb_api_t api), void *closure); - -template void call(const char *api, const char *verb, struct json_object *args, void (*callback)(T*closure, int iserror, struct json_object *result, afb_api_t api), T *closure); - -bool callsync(const char *api, const char *verb, struct json_object *args, struct json_object *&result); -#else -void call(const char *api, const char *verb, struct json_object *args, void (*callback)(void*closure, int iserror, struct json_object *result), void *closure); - -template void call(const char *api, const char *verb, struct json_object *args, void (*callback)(T*closure, int iserror, struct json_object *result), T *closure); -#endif - -bool callsync(const char *api, const char *verb, struct json_object *args, struct json_object *&result); - -/*************************************************************************/ -/* effective declaration of classes */ -/*************************************************************************/ - -/* events */ -class event -{ - afb_event_t event_; -public: - event() { invalidate(); } - event(afb_event_t e); - event(const event &other); - event &operator=(const event &other); - - operator afb_event_t() const; - afb_event_t operator->() const; - - operator bool() const; - bool is_valid() const; - - void invalidate(); - - int broadcast(json_object *object) const; - int push(json_object *object) const; - - void unref(); - void addref(); - const char *name() const; -}; - -/* args */ -class arg -{ - struct afb_arg arg_; -public: - arg() = delete; - arg(const struct afb_arg &a); - arg(const arg &other); - arg &operator=(const arg &other); - - operator const struct afb_arg&() const; - - bool has_name() const; - bool has_value() const; - bool has_path() const; - - const char *name() const; - const char *value() const; - const char *path() const; -}; - -/* req(uest) */ -class req -{ - afb_req_t req_; - -public: - req() = delete; - req(afb_req_t r); - req(const req &other); - req &operator=(const req &other); - - operator afb_req_t() const; - afb_req_t operator->() const; - - operator bool() const; - bool is_valid() const; - - arg get(const char *name) const; - - const char *value(const char *name) const; - - const char *path(const char *name) const; - - json_object *json() const; - - void reply(json_object *obj = nullptr, const char *error = nullptr, const char *info = nullptr) const; - void replyf(json_object *obj, const char *error, const char *info, ...) const; - void replyv(json_object *obj, const char *error, const char *info, va_list args) const; - - void success(json_object *obj = nullptr, const char *info = nullptr) const; - void successf(json_object *obj, const char *info, ...) const; - void successv(json_object *obj, const char *info, va_list args) const; - - void fail(const char *error = "failed", const char *info = nullptr) const; - void failf(const char *error, const char *info, ...) const; - void failv(const char *error, const char *info, va_list args) const; - - template < class T > T *context() const; - - void addref() const; - - void unref() const; - - void session_close() const; - - bool session_set_LOA(unsigned level) const; - - bool subscribe(const event &event) const; - - bool unsubscribe(const event &event) const; - - void subcall(const char *api, const char *verb, json_object *args, void (*callback)(void *closure, int iserror, json_object *result, afb_req_t req), void *closure) const; - template void subcall(const char *api, const char *verb, json_object *args, void (*callback)(T *closure, int iserror, json_object *result, afb_req_t req), T *closure) const; - - bool subcallsync(const char *api, const char *verb, json_object *args, struct json_object *&result) const; - -#if AFB_BINDING_VERSION >= 3 - void subcall(const char *api, const char *verb, json_object *args, int flags, void (*callback)(void *closure, json_object *object, const char *error, const char *info, afb_req_t req), void *closure) const; - - template void subcall(const char *api, const char *verb, json_object *args, int flags, void (*callback)(T *closure, json_object *object, const char *error, const char *info, afb_req_t req), T *closure) const; - - bool subcallsync(const char *api, const char *verb, json_object *args, int flags, struct json_object *&object, char *&error, char *&info) const; -#endif - - void verbose(int level, const char *file, int line, const char * func, const char *fmt, va_list args) const; - - void verbose(int level, const char *file, int line, const char * func, const char *fmt, ...) const; - - bool has_permission(const char *permission) const; - - char *get_application_id() const; - - int get_uid() const; - - json_object *get_client_info() const; -}; - -/*************************************************************************/ -/* effective declaration of classes */ -/*************************************************************************/ -///////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////// - - -/*************************************************************************/ -/* effective declaration of classes */ -/*************************************************************************/ - -/* events */ -inline event::event(afb_event_t e) : event_(e) { } -inline event::event(const event &other) : event_(other.event_) { } -inline event &event::operator=(const event &other) { event_ = other.event_; return *this; } - -inline event::operator afb_event_t() const { return event_; } -inline afb_event_t event::operator->() const { return event_; } - -inline event::operator bool() const { return is_valid(); } -inline bool event::is_valid() const { return afb_event_is_valid(event_); } - -#if AFB_BINDING_VERSION >= 3 -inline void event::invalidate() { event_ = nullptr; } -#else -inline void event::invalidate() { event_ = { nullptr, nullptr }; } -#endif - -inline int event::broadcast(json_object *object) const { return afb_event_broadcast(event_, object); } -inline int event::push(json_object *object) const { return afb_event_push(event_, object); } - -inline void event::unref() { afb_event_unref(event_); invalidate(); } -inline void event::addref() { afb_event_addref(event_); } -inline const char *event::name() const { return afb_event_name(event_); } - -/* args */ -inline arg::arg(const struct afb_arg &a) : arg_(a) {} -inline arg::arg(const arg &other) : arg_(other.arg_) {} -inline arg &arg::operator=(const arg &other) { arg_ = other.arg_; return *this; } - -inline arg::operator const struct afb_arg&() const { return arg_; } - -inline bool arg::has_name() const { return !!arg_.name; } -inline bool arg::has_value() const { return !!arg_.value; } -inline bool arg::has_path() const { return !!arg_.path; } - -inline const char *arg::name() const { return arg_.name; } -inline const char *arg::value() const { return arg_.value; } -inline const char *arg::path() const { return arg_.path; } - -/* req(uests)s */ - - -inline req::req(afb_req_t r) : req_(r) {} -inline req::req(const req &other) : req_(other.req_) {} -inline req &req::operator=(const req &other) { req_ = other.req_; return *this; } - -inline req::operator afb_req_t() const { return req_; } -inline afb_req_t req::operator->() const { return req_; } - -inline req::operator bool() const { return is_valid(); } -inline bool req::is_valid() const { return afb_req_is_valid(req_); } - -inline arg req::get(const char *name) const { return arg(afb_req_get(req_, name)); } - -inline const char *req::value(const char *name) const { return afb_req_value(req_, name); } - -inline const char *req::path(const char *name) const { return afb_req_path(req_, name); } - -inline json_object *req::json() const { return afb_req_json(req_); } - -inline void req::reply(json_object *obj, const char *error, const char *info) const { afb_req_reply(req_, obj, error, info); } -inline void req::replyv(json_object *obj, const char *error, const char *info, va_list args) const { afb_req_reply_v(req_, obj, error, info, args); } -inline void req::replyf(json_object *obj, const char *error, const char *info, ...) const -{ - va_list args; - va_start(args, info); - replyv(obj, error, info, args); - va_end(args); -} - -inline void req::success(json_object *obj, const char *info) const { reply(obj, nullptr, info); } -inline void req::successv(json_object *obj, const char *info, va_list args) const { replyv(obj, nullptr, info, args); } -inline void req::successf(json_object *obj, const char *info, ...) const -{ - va_list args; - va_start(args, info); - successv(obj, info, args); - va_end(args); -} - -inline void req::fail(const char *error, const char *info) const { reply(nullptr, error, info); } -inline void req::failv(const char *error, const char *info, va_list args) const { replyv(nullptr, error, info, args); } -inline void req::failf(const char *error, const char *info, ...) const -{ - va_list args; - va_start(args, info); - failv(error, info, args); - va_end(args); -} - -template < class T > -inline T *req::context() const -{ -#if AFB_BINDING_VERSION >= 3 - T* (*creater)(void*) = [](){return new T();}; - void (*freer)(T*) = [](T*t){delete t;}; - return reinterpret_cast(afb_req_context(req_, 0, - reinterpret_cast(creater), - reinterpret_cast(freer), nullptr)); -#else - T* (*creater)() = [](){return new T();}; - void (*freer)(T*) = [](T*t){delete t;}; - return reinterpret_cast(afb_req_context(req_, - reinterpret_cast(creater), - reinterpret_cast(freer))); -#endif -} - -inline void req::addref() const { afb_req_addref(req_); } - -inline void req::unref() const { afb_req_unref(req_); } - -inline void req::session_close() const { afb_req_session_close(req_); } - -inline bool req::session_set_LOA(unsigned level) const { return !afb_req_session_set_LOA(req_, level); } - -inline bool req::subscribe(const event &event) const { return !afb_req_subscribe(req_, event); } - -inline bool req::unsubscribe(const event &event) const { return !afb_req_unsubscribe(req_, event); } - - - - - -#if AFB_BINDING_VERSION >= 3 - -inline void req::subcall(const char *api, const char *verb, json_object *args, int flags, void (*callback)(void *closure, json_object *result, const char *error, const char *info, afb_req_t req), void *closure) const -{ - afb_req_subcall(req_, api, verb, args, flags, callback, closure); -} - -template -inline void req::subcall(const char *api, const char *verb, json_object *args, int flags, void (*callback)(T *closure, json_object *result, const char *error, const char *info, afb_req_t req), T *closure) const -{ - subcall(api, verb, args, flags, reinterpret_cast(callback), reinterpret_cast(closure)); -} - -inline bool req::subcallsync(const char *api, const char *verb, json_object *args, int flags, struct json_object *&object, char *&error, char *&info) const -{ - return !afb_req_subcall_sync(req_, api, verb, args, flags, &object, &error, &info); -} - -#endif - -inline void req::subcall(const char *api, const char *verb, json_object *args, void (*callback)(void *closure, int iserror, json_object *result, afb_req_t req), void *closure) const -{ -#if AFB_BINDING_VERSION >= 3 - afb_req_subcall_legacy(req_, api, verb, args, callback, closure); -#else - afb_req_subcall_req(req_, api, verb, args, callback, closure); -#endif -} - -template -inline void req::subcall(const char *api, const char *verb, json_object *args, void (*callback)(T *closure, int iserror, json_object *result, afb_req_t req), T *closure) const -{ - subcall(api, verb, args, reinterpret_cast(callback), reinterpret_cast(closure)); -} - -inline bool req::subcallsync(const char *api, const char *verb, json_object *args, struct json_object *&result) const -{ -#if AFB_BINDING_VERSION >= 3 - return !afb_req_subcall_sync_legacy(req_, api, verb, args, &result); -#else - return !afb_req_subcall_sync(req_, api, verb, args, &result); -#endif -} - -inline void req::verbose(int level, const char *file, int line, const char * func, const char *fmt, va_list args) const -{ - afb_req_verbose(req_, level, file, line, func, fmt, args); -} - -inline void req::verbose(int level, const char *file, int line, const char * func, const char *fmt, ...) const -{ - va_list args; - va_start(args, fmt); - afb_req_verbose(req_, level, file, line, func, fmt, args); - va_end(args); -} - -inline bool req::has_permission(const char *permission) const -{ - return bool(afb_req_has_permission(req_, permission)); -} - -inline char *req::get_application_id() const -{ - return afb_req_get_application_id(req_); -} - -inline int req::get_uid() const -{ - return afb_req_get_uid(req_); -} - -inline json_object *req::get_client_info() const -{ - return afb_req_get_client_info(req_); -} - -/* commons */ -inline int broadcast_event(const char *name, json_object *object) - { return afb_daemon_broadcast_event(name, object); } - -inline event make_event(const char *name) - { return afb_daemon_make_event(name); } - -inline void verbose(int level, const char *file, int line, const char * func, const char *fmt, va_list args) - { afb_daemon_verbose(level, file, line, func, fmt, args); } - -inline void verbose(int level, const char *file, int line, const char * func, const char *fmt, ...) - { va_list args; va_start(args, fmt); verbose(level, file, line, func, fmt, args); va_end(args); } - -inline int rootdir_get_fd() - { return afb_daemon_rootdir_get_fd(); } - -inline int rootdir_open_locale_fd(const char *filename, int flags, const char *locale) - { return afb_daemon_rootdir_open_locale(filename, flags, locale); } - -inline int queue_job(void (*callback)(int signum, void *arg), void *argument, void *group, int timeout) - { return afb_daemon_queue_job(callback, argument, group, timeout); } - -inline int require_api(const char *apiname, bool initialized) - { return afb_daemon_require_api(apiname, int(initialized)); } - -inline int add_alias(const char *apiname, const char *aliasname) - { return afb_daemon_add_alias(apiname, aliasname); } - -#if AFB_BINDING_VERSION >= 3 -inline int logmask() - { return afb_get_logmask(); } -#else -inline int logmask() - { return (1 << (1 + afb_get_verbosity() + AFB_SYSLOG_LEVEL_ERROR)) - 1; } -#endif - -inline bool wants_errors() - { return AFB_SYSLOG_MASK_WANT_ERROR(logmask()); } - -inline bool wants_warnings() - { return AFB_SYSLOG_MASK_WANT_WARNING(logmask()); } - -inline bool wants_notices() - { return AFB_SYSLOG_MASK_WANT_NOTICE(logmask()); } - -inline bool wants_infos() - { return AFB_SYSLOG_MASK_WANT_INFO(logmask()); } - -inline bool wants_debugs() - { return AFB_SYSLOG_MASK_WANT_DEBUG(logmask()); } - -#if AFB_BINDING_VERSION >= 3 -inline void call(const char *api, const char *verb, struct json_object *args, void (*callback)(void*closure, struct json_object *result, const char *error, const char *info, afb_api_t api), void *closure) -{ - afb_service_call(api, verb, args, callback, closure); -} - -template -inline void call(const char *api, const char *verb, struct json_object *args, void (*callback)(T*closure, struct json_object *result, const char *error, const char *info, afb_api_t api), T *closure) -{ - afb_service_call(api, verb, args, reinterpret_cast(callback), reinterpret_cast(closure)); -} - -inline bool callsync(const char *api, const char *verb, struct json_object *args, struct json_object *&result, char *&error, char *&info) -{ - return !!afb_service_call_sync(api, verb, args, &result, &error, &info); -} -#else -inline void call(const char *api, const char *verb, struct json_object *args, void (*callback)(void*closure, int iserror, struct json_object *result), void *closure) -{ - afb_service_call(api, verb, args, callback, closure); -} - -template -inline void call(const char *api, const char *verb, struct json_object *args, void (*callback)(T*closure, int iserror, struct json_object *result), T *closure) -{ - afb_service_call(api, verb, args, reinterpret_cast(callback), reinterpret_cast(closure)); -} - -inline bool callsync(const char *api, const char *verb, struct json_object *args, struct json_object *&result) -{ - return !!afb_service_call_sync(api, verb, args, &result); -} -#endif - -/*************************************************************************/ -/* declaration of the binding's authorization s */ -/*************************************************************************/ - -constexpr afb_auth auth_no() -{ - afb_auth r = { afb_auth_No, 0, 0}; - r.type = afb_auth_No; - return r; -} - -constexpr afb_auth auth_yes() -{ - afb_auth r = { afb_auth_No, 0, 0}; - r.type = afb_auth_Yes; - return r; -} - -constexpr afb_auth auth_token() -{ - afb_auth r = { afb_auth_No, 0, 0}; - r.type = afb_auth_Token; - return r; -} - -constexpr afb_auth auth_LOA(unsigned loa) -{ - afb_auth r = { afb_auth_No, 0, 0}; - r.type = afb_auth_LOA; - r.loa = loa; - return r; -} - -constexpr afb_auth auth_permission(const char *permission) -{ - afb_auth r = { afb_auth_No, 0, 0}; - r.type = afb_auth_Permission; - r.text = permission; - return r; -} - -constexpr afb_auth auth_not(const afb_auth *other) -{ - afb_auth r = { afb_auth_No, 0, 0}; - r.type = afb_auth_Not; - r.first = other; - return r; -} - -constexpr afb_auth auth_not(const afb_auth &other) -{ - return auth_not(&other); -} - -constexpr afb_auth auth_or(const afb_auth *first, const afb_auth *next) -{ - afb_auth r = { afb_auth_No, 0, 0}; - r.type = afb_auth_Or; - r.first = first; - r.next = next; - return r; -} - -constexpr afb_auth auth_or(const afb_auth &first, const afb_auth &next) -{ - return auth_or(&first, &next); -} - -constexpr afb_auth auth_and(const afb_auth *first, const afb_auth *next) -{ - afb_auth r = { afb_auth_No, 0, 0}; - r.type = afb_auth_And; - r.first = first; - r.next = next; - return r; -} - -constexpr afb_auth auth_and(const afb_auth &first, const afb_auth &next) -{ - return auth_and(&first, &next); -} - -constexpr afb_verb_t verb( - const char *name, - void (*callback)(afb_req_t), - const char *info = nullptr, - uint16_t session = 0, - const afb_auth *auth = nullptr -#if AFB_BINDING_VERSION >= 3 - , - bool glob = false, - void *vcbdata = nullptr -#endif -) -{ -#if AFB_BINDING_VERSION >= 3 - afb_verb_t r = { 0, 0, 0, 0, 0, 0, 0 }; -#else - afb_verb_t r = { 0, 0, 0, 0, 0 }; -#endif - r.verb = name; - r.callback = callback; - r.info = info; - r.session = session; - r.auth = auth; -#if AFB_BINDING_VERSION >= 3 - r.glob = (unsigned)glob; - r.vcbdata = vcbdata; -#endif - return r; -} - -constexpr afb_verb_t verbend() -{ - afb_verb_t r = verb(nullptr, nullptr); - return r; -} - -constexpr afb_binding_t binding( - const char *name, - const afb_verb_t *verbs, - const char *info = nullptr, -#if AFB_BINDING_VERSION >= 3 - int (*init)(afb_api_t) = nullptr, - const char *specification = nullptr, - void (*onevent)(afb_api_t, const char*, struct json_object*) = nullptr, - bool noconcurrency = false, - int (*preinit)(afb_api_t) = nullptr, - void *userdata = nullptr -#else - int (*init)() = nullptr, - const char *specification = nullptr, - void (*onevent)(const char*, struct json_object*) = nullptr, - bool noconcurrency = false, - int (*preinit)() = nullptr -#endif -) -{ -#if AFB_BINDING_VERSION >= 3 - afb_binding_t r = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -#else - afb_binding_t r = { 0, 0, 0, 0, 0, 0, 0, 0 }; -#endif - r.api = name; - r.specification = specification; - r.info = info; - r.verbs = verbs; - r.preinit = preinit; - r.init = init; - r.onevent = onevent; - r.noconcurrency = noconcurrency ? 1 : 0; -#if AFB_BINDING_VERSION >= 3 - r.userdata = userdata; -#endif - return r; -}; - -/*************************************************************************/ -/*** E N D ***/ -/*************************************************************************/ -} diff --git a/include/afb/c++/binding b/include/afb/c++/binding new file mode 100644 index 00000000..5858dff7 --- /dev/null +++ b/include/afb/c++/binding @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2016, 2017, 2018 "IoT.bzh" + * Author: José Bollo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#pragma once +#include "binding-wrap.hpp" +#include "binding-object.hpp" diff --git a/include/afb/c++/binding-object.hpp b/include/afb/c++/binding-object.hpp new file mode 100644 index 00000000..f9c3bcab --- /dev/null +++ b/include/afb/c++/binding-object.hpp @@ -0,0 +1,323 @@ +#pragma once + +/* + * Copyright (C) 2018 "IoT.bzh" + * Author Loïc Collignon + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "../afb-binding.h" +#include +#include + +namespace afb +{ + /** + * @brief Create a new API. + * @tparam TApi The Api's concrete class to create an instance from. + * @param[in] handle Parent API. + * @param[in] name API's name. + * @param[in] info API's description. + * @param[in] noconcurrency Zero for a reentrant API, non-zero otherwise. + * @return The created API. + */ + template + TApi* new_api(afb_api_t handle, const std::string& name, const std::string& info = "", int noconcurrency = 1) + { + TApi* api = new TApi(); + afb_api_new_api( + handle, + name.c_str(), + info == "" ? nullptr : info.c_str(), + noconcurrency, + TApi::Traits::preinit, + api + ); + return api; + } + + /** + * @brief Default Api's traits implementation. + * @tparam TApi The Api's concrete class. + */ + template + struct ApiTraits + { + /** + * @brief TApi's method pointer. + */ + using TVerbCallback = void(TApi::*)(req); + + /*** + * @brief TApi's const method pointer. + */ + using TVerbCallbackConst = void(TApi::*)(req) const; + + /** + * @brief Pre-init callback for an api created using @c afb::api::new_api. + * @param[in] closure Pointer to the API object. + * @param[in] handle Handle of the API. + * @return Zero on success, non-zero otherwise. + */ + static int preinit(void* closure, afb_api_t handle) + { + assert(closure != nullptr); + assert(handle != nullptr); + + afb_api_set_userdata(handle, closure); + + TApi* api = reinterpret_cast(closure); + + if (afb_api_on_init(handle, TApi::Traits::init)) + { + AFB_API_ERROR(handle, "Failed to register init handler callback."); + return -1; + } + + if (afb_api_on_event(handle, TApi::Traits::event)) + { + AFB_API_ERROR(handle, "Failed to register event handler callback."); + return -2; + } + + api->handle_ = handle; + return api->preinit(handle); + } + + /** + * @brief Init callback for an api created using @c afb::api::new_api. + * @param[in] handle Handle to the API to initialize. + * @return Zero on success, non-zero otherwise. + */ + static int init(afb_api_t handle) + { + assert(handle != nullptr); + + void* userdata = afb_api_get_userdata(handle); + assert(userdata != nullptr); + + TApi* api = reinterpret_cast(userdata); + return api->init(); + } + + /** + * @brief Event callback for an api created using @c afb::api::new_api. + * @param[in] handle Handle to the API that is receiving an event. + * @param[in] event The event's name. + * @param[in] object The event's json argument. + */ + static void event(afb_api_t handle, const char* event, json_object* object) + { + assert(handle != nullptr); + + void* userdata = afb_api_get_userdata(handle); + assert(userdata != nullptr); + + TApi* api = reinterpret_cast(userdata); + api->event(event, object); + } + + /** + * @brief Verb callback for a verb added using @c afb::api::add_verb. + * @tparam callback TApi's method to call + * @param[in] r Request to handle. + */ + template + static void verb(afb_req_t r) + { + assert(r != nullptr); + + afb_api_t handle = afb_req_get_api(r); + if (handle) + { + void* userdata = afb_api_get_userdata(handle); + if (userdata) + { + TApi* api = reinterpret_cast(userdata); + (api->*callback)(afb::req(r)); + } + else + { + afb_req_fail(r, "Failed to get the API object!", nullptr); + } + } + else + { + afb_req_fail(r, "Failed to get the corresponding API from the query!", nullptr); + } + } + + /** + * @brief Verb callback for a verb added using @c afb::api::add_verb. + * @tparam callback TApi's const method to call. + * @param[in] req Request to handle. + */ + template + static void verb(afb_req_t r) + { + assert(r != nullptr); + + afb_api_t handle = afb_req_get_api(r); + if (handle) + { + void* userdata = afb_api_get_userdata(handle); + if (userdata) + { + TApi* api = reinterpret_cast(userdata); + (api->*callback)(afb::req(r)); + } + else + { + afb_req_fail(r, "Failed to get the API object!", nullptr); + } + } + else + { + afb_req_fail(r, "Failed to get the corresponding API from the query!", nullptr); + } + } + }; + + /** + * @brief Base class for API implementation. + * @tparam TApi The Api's concrete class. + * @tparam TTraits The Api's static callback implementation. + */ + template < + typename TApi, + typename TTraits = ApiTraits + > + class base_api_t + { + friend TTraits; + + public: + using Traits = TTraits; + + private: + // Non-copyable + base_api_t(const base_api_t&) = delete; + base_api_t& operator=(const base_api_t&) = delete; + + protected: + afb_api_t handle_; + + /** + * @brief Default constructor. + */ + explicit base_api_t() = default; + + /** + * @brief Move constructor. + */ + explicit base_api_t(base_api_t&&) = default; + + /** + * @brief Add a verb to an API. + * @param[in] api API on which the verb should be added. + * @param[in] verb Verb's name. + * @param[in] info Verb's description. + * @param[in] auth Verb's permissions required. + * @param[in] session Verb's session handling. + * @param[in] glob is the verb glob name. + * @return Zero if success, non-zero otherwise. + */ + template + int add_verb(const std::string& verb, const std::string& info, void* vcbdata = nullptr, const struct afb_auth* auth = nullptr, uint32_t session = AFB_SESSION_NONE_X2, int glob = 0) + { + return afb_api_add_verb( + handle_, + verb.c_str(), + info == "" ? nullptr : info.c_str(), + TTraits::template verb, + vcbdata, + auth, + session, + glob + ); + } + + /** + * @brief Add a verb to an API. + * @param[in] api API on which the verb should be added. + * @param[in] verb Verb's name. + * @param[in] info Verb's description. + * @param[in] auth Verb's permissions required. + * @param[in] session Verb's session handling. + * @param[in] glob is the verb glob name. + * @return Zero if success, non-zero otherwise. + */ + template + int add_verb(const std::string& verb, const std::string& info, void* vcbdata = nullptr, const struct afb_auth* auth = nullptr, uint32_t session = AFB_SESSION_NONE_X2, int glob = 0) + { + return afb_api_add_verb( + handle_, + verb.c_str(), + info == "" ? nullptr : info.c_str(), + TTraits::template verb, + vcbdata, + auth, + session, + glob + ); + } + + public: + /** + * @brief Move assignation operator. + */ + base_api_t& operator=(base_api_t&&) = default; + + /** + * @brief Get the API's handle. + * @return The API's handle. + */ + afb_api_t handle() const { return handle_; } + + /** + * @brief Implicit conversion to C handle. + * @return The API's handle. + */ + operator afb_api_t() const { return handle_; } + + /** + * @brief Destructor. + */ + virtual ~base_api_t() + { + if (handle_ && afb_api_delete_api(handle_)) + AFB_API_ERROR(handle_, "Failed to delete API."); + } + + /** + * @brief Called by the binder during the API's pre-init phase. + * @param[in] handle Handle representing the API on the binder's side. + * @return Zero if success, non-zero otherwise. + */ + virtual int preinit(afb_api_t handle) { return 0; } + + /** + * @brief Called by the binder during the API's init phase. + * @return Zero on success, non-zero otherwise. + */ + virtual int init() { return 0; } + + /** + * @brief Called by the binder when an event is received for this API. + * @param[in] name Event's name. + * @param[in] arg Event's argument. + */ + virtual void event(const std::string& name, json_object* arg) { } + }; +} diff --git a/include/afb/c++/binding-wrap.hpp b/include/afb/c++/binding-wrap.hpp new file mode 100644 index 00000000..0cb64423 --- /dev/null +++ b/include/afb/c++/binding-wrap.hpp @@ -0,0 +1,692 @@ +/* + * Copyright (C) 2016-2019 "IoT.bzh" + * Author: José Bollo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include +#include +#include + +/* ensure version */ +#ifndef AFB_BINDING_VERSION +# define AFB_BINDING_VERSION 3 +#endif + +/* check the version */ +#if AFB_BINDING_VERSION < 2 +# error "AFB_BINDING_VERSION must be at least 2 but 3 is prefered" +#endif + +/* get C definitions of bindings */ +extern "C" { +#include "afb-binding.h" +} + +namespace afb { +/*************************************************************************/ +/* pre-declaration of classes */ +/*************************************************************************/ + +class arg; +class event; +class req; + +/*************************************************************************/ +/* declaration of functions */ +/*************************************************************************/ + +int broadcast_event(const char *name, json_object *object = nullptr); + +event make_event(const char *name); + +void verbose(int level, const char *file, int line, const char * func, const char *fmt, va_list args); + +void verbose(int level, const char *file, int line, const char * func, const char *fmt, ...); + +int rootdir_get_fd(); + +int rootdir_open_locale_fd(const char *filename, int flags, const char *locale = nullptr); + +int queue_job(void (*callback)(int signum, void *arg), void *argument, void *group, int timeout); + +int require_api(const char *apiname, bool initialized = true); + +int add_alias(const char *apiname, const char *aliasname); + +int verbosity(); + +bool wants_errors(); +bool wants_warnings(); +bool wants_notices(); +bool wants_infos(); +bool wants_debugs(); + +#if AFB_BINDING_VERSION >= 3 +void call(const char *api, const char *verb, struct json_object *args, void (*callback)(void*closure, int iserror, struct json_object *result, afb_api_t api), void *closure); + +template void call(const char *api, const char *verb, struct json_object *args, void (*callback)(T*closure, int iserror, struct json_object *result, afb_api_t api), T *closure); + +bool callsync(const char *api, const char *verb, struct json_object *args, struct json_object *&result); +#else +void call(const char *api, const char *verb, struct json_object *args, void (*callback)(void*closure, int iserror, struct json_object *result), void *closure); + +template void call(const char *api, const char *verb, struct json_object *args, void (*callback)(T*closure, int iserror, struct json_object *result), T *closure); +#endif + +bool callsync(const char *api, const char *verb, struct json_object *args, struct json_object *&result); + +/*************************************************************************/ +/* effective declaration of classes */ +/*************************************************************************/ + +/* events */ +class event +{ + afb_event_t event_; +public: + event() { invalidate(); } + event(afb_event_t e); + event(const event &other); + event &operator=(const event &other); + + operator afb_event_t() const; + afb_event_t operator->() const; + + operator bool() const; + bool is_valid() const; + + void invalidate(); + + int broadcast(json_object *object) const; + int push(json_object *object) const; + + void unref(); + void addref(); + const char *name() const; +}; + +/* args */ +class arg +{ + struct afb_arg arg_; +public: + arg() = delete; + arg(const struct afb_arg &a); + arg(const arg &other); + arg &operator=(const arg &other); + + operator const struct afb_arg&() const; + + bool has_name() const; + bool has_value() const; + bool has_path() const; + + const char *name() const; + const char *value() const; + const char *path() const; +}; + +/* req(uest) */ +class req +{ + afb_req_t req_; + +public: + req() = delete; + req(afb_req_t r); + req(const req &other); + req &operator=(const req &other); + + operator afb_req_t() const; + afb_req_t operator->() const; + + operator bool() const; + bool is_valid() const; + + arg get(const char *name) const; + + const char *value(const char *name) const; + + const char *path(const char *name) const; + + json_object *json() const; + + void reply(json_object *obj = nullptr, const char *error = nullptr, const char *info = nullptr) const; + void replyf(json_object *obj, const char *error, const char *info, ...) const; + void replyv(json_object *obj, const char *error, const char *info, va_list args) const; + + void success(json_object *obj = nullptr, const char *info = nullptr) const; + void successf(json_object *obj, const char *info, ...) const; + void successv(json_object *obj, const char *info, va_list args) const; + + void fail(const char *error = "failed", const char *info = nullptr) const; + void failf(const char *error, const char *info, ...) const; + void failv(const char *error, const char *info, va_list args) const; + + template < class T > T *context() const; + + void addref() const; + + void unref() const; + + void session_close() const; + + bool session_set_LOA(unsigned level) const; + + bool subscribe(const event &event) const; + + bool unsubscribe(const event &event) const; + + void subcall(const char *api, const char *verb, json_object *args, void (*callback)(void *closure, int iserror, json_object *result, afb_req_t req), void *closure) const; + template void subcall(const char *api, const char *verb, json_object *args, void (*callback)(T *closure, int iserror, json_object *result, afb_req_t req), T *closure) const; + + bool subcallsync(const char *api, const char *verb, json_object *args, struct json_object *&result) const; + +#if AFB_BINDING_VERSION >= 3 + void subcall(const char *api, const char *verb, json_object *args, int flags, void (*callback)(void *closure, json_object *object, const char *error, const char *info, afb_req_t req), void *closure) const; + + template void subcall(const char *api, const char *verb, json_object *args, int flags, void (*callback)(T *closure, json_object *object, const char *error, const char *info, afb_req_t req), T *closure) const; + + bool subcallsync(const char *api, const char *verb, json_object *args, int flags, struct json_object *&object, char *&error, char *&info) const; +#endif + + void verbose(int level, const char *file, int line, const char * func, const char *fmt, va_list args) const; + + void verbose(int level, const char *file, int line, const char * func, const char *fmt, ...) const; + + bool has_permission(const char *permission) const; + + char *get_application_id() const; + + int get_uid() const; + + json_object *get_client_info() const; +}; + +/*************************************************************************/ +/* effective declaration of classes */ +/*************************************************************************/ +///////////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////////////// + + +/*************************************************************************/ +/* effective declaration of classes */ +/*************************************************************************/ + +/* events */ +inline event::event(afb_event_t e) : event_(e) { } +inline event::event(const event &other) : event_(other.event_) { } +inline event &event::operator=(const event &other) { event_ = other.event_; return *this; } + +inline event::operator afb_event_t() const { return event_; } +inline afb_event_t event::operator->() const { return event_; } + +inline event::operator bool() const { return is_valid(); } +inline bool event::is_valid() const { return afb_event_is_valid(event_); } + +#if AFB_BINDING_VERSION >= 3 +inline void event::invalidate() { event_ = nullptr; } +#else +inline void event::invalidate() { event_ = { nullptr, nullptr }; } +#endif + +inline int event::broadcast(json_object *object) const { return afb_event_broadcast(event_, object); } +inline int event::push(json_object *object) const { return afb_event_push(event_, object); } + +inline void event::unref() { afb_event_unref(event_); invalidate(); } +inline void event::addref() { afb_event_addref(event_); } +inline const char *event::name() const { return afb_event_name(event_); } + +/* args */ +inline arg::arg(const struct afb_arg &a) : arg_(a) {} +inline arg::arg(const arg &other) : arg_(other.arg_) {} +inline arg &arg::operator=(const arg &other) { arg_ = other.arg_; return *this; } + +inline arg::operator const struct afb_arg&() const { return arg_; } + +inline bool arg::has_name() const { return !!arg_.name; } +inline bool arg::has_value() const { return !!arg_.value; } +inline bool arg::has_path() const { return !!arg_.path; } + +inline const char *arg::name() const { return arg_.name; } +inline const char *arg::value() const { return arg_.value; } +inline const char *arg::path() const { return arg_.path; } + +/* req(uests)s */ + + +inline req::req(afb_req_t r) : req_(r) {} +inline req::req(const req &other) : req_(other.req_) {} +inline req &req::operator=(const req &other) { req_ = other.req_; return *this; } + +inline req::operator afb_req_t() const { return req_; } +inline afb_req_t req::operator->() const { return req_; } + +inline req::operator bool() const { return is_valid(); } +inline bool req::is_valid() const { return afb_req_is_valid(req_); } + +inline arg req::get(const char *name) const { return arg(afb_req_get(req_, name)); } + +inline const char *req::value(const char *name) const { return afb_req_value(req_, name); } + +inline const char *req::path(const char *name) const { return afb_req_path(req_, name); } + +inline json_object *req::json() const { return afb_req_json(req_); } + +inline void req::reply(json_object *obj, const char *error, const char *info) const { afb_req_reply(req_, obj, error, info); } +inline void req::replyv(json_object *obj, const char *error, const char *info, va_list args) const { afb_req_reply_v(req_, obj, error, info, args); } +inline void req::replyf(json_object *obj, const char *error, const char *info, ...) const +{ + va_list args; + va_start(args, info); + replyv(obj, error, info, args); + va_end(args); +} + +inline void req::success(json_object *obj, const char *info) const { reply(obj, nullptr, info); } +inline void req::successv(json_object *obj, const char *info, va_list args) const { replyv(obj, nullptr, info, args); } +inline void req::successf(json_object *obj, const char *info, ...) const +{ + va_list args; + va_start(args, info); + successv(obj, info, args); + va_end(args); +} + +inline void req::fail(const char *error, const char *info) const { reply(nullptr, error, info); } +inline void req::failv(const char *error, const char *info, va_list args) const { replyv(nullptr, error, info, args); } +inline void req::failf(const char *error, const char *info, ...) const +{ + va_list args; + va_start(args, info); + failv(error, info, args); + va_end(args); +} + +template < class T > +inline T *req::context() const +{ +#if AFB_BINDING_VERSION >= 3 + T* (*creater)(void*) = [](){return new T();}; + void (*freer)(T*) = [](T*t){delete t;}; + return reinterpret_cast(afb_req_context(req_, 0, + reinterpret_cast(creater), + reinterpret_cast(freer), nullptr)); +#else + T* (*creater)() = [](){return new T();}; + void (*freer)(T*) = [](T*t){delete t;}; + return reinterpret_cast(afb_req_context(req_, + reinterpret_cast(creater), + reinterpret_cast(freer))); +#endif +} + +inline void req::addref() const { afb_req_addref(req_); } + +inline void req::unref() const { afb_req_unref(req_); } + +inline void req::session_close() const { afb_req_session_close(req_); } + +inline bool req::session_set_LOA(unsigned level) const { return !afb_req_session_set_LOA(req_, level); } + +inline bool req::subscribe(const event &event) const { return !afb_req_subscribe(req_, event); } + +inline bool req::unsubscribe(const event &event) const { return !afb_req_unsubscribe(req_, event); } + + + + + +#if AFB_BINDING_VERSION >= 3 + +inline void req::subcall(const char *api, const char *verb, json_object *args, int flags, void (*callback)(void *closure, json_object *result, const char *error, const char *info, afb_req_t req), void *closure) const +{ + afb_req_subcall(req_, api, verb, args, flags, callback, closure); +} + +template +inline void req::subcall(const char *api, const char *verb, json_object *args, int flags, void (*callback)(T *closure, json_object *result, const char *error, const char *info, afb_req_t req), T *closure) const +{ + subcall(api, verb, args, flags, reinterpret_cast(callback), reinterpret_cast(closure)); +} + +inline bool req::subcallsync(const char *api, const char *verb, json_object *args, int flags, struct json_object *&object, char *&error, char *&info) const +{ + return !afb_req_subcall_sync(req_, api, verb, args, flags, &object, &error, &info); +} + +#endif + +inline void req::subcall(const char *api, const char *verb, json_object *args, void (*callback)(void *closure, int iserror, json_object *result, afb_req_t req), void *closure) const +{ +#if AFB_BINDING_VERSION >= 3 + afb_req_subcall_legacy(req_, api, verb, args, callback, closure); +#else + afb_req_subcall_req(req_, api, verb, args, callback, closure); +#endif +} + +template +inline void req::subcall(const char *api, const char *verb, json_object *args, void (*callback)(T *closure, int iserror, json_object *result, afb_req_t req), T *closure) const +{ + subcall(api, verb, args, reinterpret_cast(callback), reinterpret_cast(closure)); +} + +inline bool req::subcallsync(const char *api, const char *verb, json_object *args, struct json_object *&result) const +{ +#if AFB_BINDING_VERSION >= 3 + return !afb_req_subcall_sync_legacy(req_, api, verb, args, &result); +#else + return !afb_req_subcall_sync(req_, api, verb, args, &result); +#endif +} + +inline void req::verbose(int level, const char *file, int line, const char * func, const char *fmt, va_list args) const +{ + afb_req_verbose(req_, level, file, line, func, fmt, args); +} + +inline void req::verbose(int level, const char *file, int line, const char * func, const char *fmt, ...) const +{ + va_list args; + va_start(args, fmt); + afb_req_verbose(req_, level, file, line, func, fmt, args); + va_end(args); +} + +inline bool req::has_permission(const char *permission) const +{ + return bool(afb_req_has_permission(req_, permission)); +} + +inline char *req::get_application_id() const +{ + return afb_req_get_application_id(req_); +} + +inline int req::get_uid() const +{ + return afb_req_get_uid(req_); +} + +inline json_object *req::get_client_info() const +{ + return afb_req_get_client_info(req_); +} + +/* commons */ +inline int broadcast_event(const char *name, json_object *object) + { return afb_daemon_broadcast_event(name, object); } + +inline event make_event(const char *name) + { return afb_daemon_make_event(name); } + +inline void verbose(int level, const char *file, int line, const char * func, const char *fmt, va_list args) + { afb_daemon_verbose(level, file, line, func, fmt, args); } + +inline void verbose(int level, const char *file, int line, const char * func, const char *fmt, ...) + { va_list args; va_start(args, fmt); verbose(level, file, line, func, fmt, args); va_end(args); } + +inline int rootdir_get_fd() + { return afb_daemon_rootdir_get_fd(); } + +inline int rootdir_open_locale_fd(const char *filename, int flags, const char *locale) + { return afb_daemon_rootdir_open_locale(filename, flags, locale); } + +inline int queue_job(void (*callback)(int signum, void *arg), void *argument, void *group, int timeout) + { return afb_daemon_queue_job(callback, argument, group, timeout); } + +inline int require_api(const char *apiname, bool initialized) + { return afb_daemon_require_api(apiname, int(initialized)); } + +inline int add_alias(const char *apiname, const char *aliasname) + { return afb_daemon_add_alias(apiname, aliasname); } + +#if AFB_BINDING_VERSION >= 3 +inline int logmask() + { return afb_get_logmask(); } +#else +inline int logmask() + { return (1 << (1 + afb_get_verbosity() + AFB_SYSLOG_LEVEL_ERROR)) - 1; } +#endif + +inline bool wants_errors() + { return AFB_SYSLOG_MASK_WANT_ERROR(logmask()); } + +inline bool wants_warnings() + { return AFB_SYSLOG_MASK_WANT_WARNING(logmask()); } + +inline bool wants_notices() + { return AFB_SYSLOG_MASK_WANT_NOTICE(logmask()); } + +inline bool wants_infos() + { return AFB_SYSLOG_MASK_WANT_INFO(logmask()); } + +inline bool wants_debugs() + { return AFB_SYSLOG_MASK_WANT_DEBUG(logmask()); } + +#if AFB_BINDING_VERSION >= 3 +inline void call(const char *api, const char *verb, struct json_object *args, void (*callback)(void*closure, struct json_object *result, const char *error, const char *info, afb_api_t api), void *closure) +{ + afb_service_call(api, verb, args, callback, closure); +} + +template +inline void call(const char *api, const char *verb, struct json_object *args, void (*callback)(T*closure, struct json_object *result, const char *error, const char *info, afb_api_t api), T *closure) +{ + afb_service_call(api, verb, args, reinterpret_cast(callback), reinterpret_cast(closure)); +} + +inline bool callsync(const char *api, const char *verb, struct json_object *args, struct json_object *&result, char *&error, char *&info) +{ + return !!afb_service_call_sync(api, verb, args, &result, &error, &info); +} +#else +inline void call(const char *api, const char *verb, struct json_object *args, void (*callback)(void*closure, int iserror, struct json_object *result), void *closure) +{ + afb_service_call(api, verb, args, callback, closure); +} + +template +inline void call(const char *api, const char *verb, struct json_object *args, void (*callback)(T*closure, int iserror, struct json_object *result), T *closure) +{ + afb_service_call(api, verb, args, reinterpret_cast(callback), reinterpret_cast(closure)); +} + +inline bool callsync(const char *api, const char *verb, struct json_object *args, struct json_object *&result) +{ + return !!afb_service_call_sync(api, verb, args, &result); +} +#endif + +/*************************************************************************/ +/* declaration of the binding's authorization s */ +/*************************************************************************/ + +constexpr afb_auth auth_no() +{ + afb_auth r = { afb_auth_No, 0, 0}; + r.type = afb_auth_No; + return r; +} + +constexpr afb_auth auth_yes() +{ + afb_auth r = { afb_auth_No, 0, 0}; + r.type = afb_auth_Yes; + return r; +} + +constexpr afb_auth auth_token() +{ + afb_auth r = { afb_auth_No, 0, 0}; + r.type = afb_auth_Token; + return r; +} + +constexpr afb_auth auth_LOA(unsigned loa) +{ + afb_auth r = { afb_auth_No, 0, 0}; + r.type = afb_auth_LOA; + r.loa = loa; + return r; +} + +constexpr afb_auth auth_permission(const char *permission) +{ + afb_auth r = { afb_auth_No, 0, 0}; + r.type = afb_auth_Permission; + r.text = permission; + return r; +} + +constexpr afb_auth auth_not(const afb_auth *other) +{ + afb_auth r = { afb_auth_No, 0, 0}; + r.type = afb_auth_Not; + r.first = other; + return r; +} + +constexpr afb_auth auth_not(const afb_auth &other) +{ + return auth_not(&other); +} + +constexpr afb_auth auth_or(const afb_auth *first, const afb_auth *next) +{ + afb_auth r = { afb_auth_No, 0, 0}; + r.type = afb_auth_Or; + r.first = first; + r.next = next; + return r; +} + +constexpr afb_auth auth_or(const afb_auth &first, const afb_auth &next) +{ + return auth_or(&first, &next); +} + +constexpr afb_auth auth_and(const afb_auth *first, const afb_auth *next) +{ + afb_auth r = { afb_auth_No, 0, 0}; + r.type = afb_auth_And; + r.first = first; + r.next = next; + return r; +} + +constexpr afb_auth auth_and(const afb_auth &first, const afb_auth &next) +{ + return auth_and(&first, &next); +} + +constexpr afb_verb_t verb( + const char *name, + void (*callback)(afb_req_t), + const char *info = nullptr, + uint16_t session = 0, + const afb_auth *auth = nullptr +#if AFB_BINDING_VERSION >= 3 + , + bool glob = false, + void *vcbdata = nullptr +#endif +) +{ +#if AFB_BINDING_VERSION >= 3 + afb_verb_t r = { 0, 0, 0, 0, 0, 0, 0 }; +#else + afb_verb_t r = { 0, 0, 0, 0, 0 }; +#endif + r.verb = name; + r.callback = callback; + r.info = info; + r.session = session; + r.auth = auth; +#if AFB_BINDING_VERSION >= 3 + r.glob = (unsigned)glob; + r.vcbdata = vcbdata; +#endif + return r; +} + +constexpr afb_verb_t verbend() +{ + afb_verb_t r = verb(nullptr, nullptr); + return r; +} + +constexpr afb_binding_t binding( + const char *name, + const afb_verb_t *verbs, + const char *info = nullptr, +#if AFB_BINDING_VERSION >= 3 + int (*init)(afb_api_t) = nullptr, + const char *specification = nullptr, + void (*onevent)(afb_api_t, const char*, struct json_object*) = nullptr, + bool noconcurrency = false, + int (*preinit)(afb_api_t) = nullptr, + void *userdata = nullptr +#else + int (*init)() = nullptr, + const char *specification = nullptr, + void (*onevent)(const char*, struct json_object*) = nullptr, + bool noconcurrency = false, + int (*preinit)() = nullptr +#endif +) +{ +#if AFB_BINDING_VERSION >= 3 + afb_binding_t r = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; +#else + afb_binding_t r = { 0, 0, 0, 0, 0, 0, 0, 0 }; +#endif + r.api = name; + r.specification = specification; + r.info = info; + r.verbs = verbs; + r.preinit = preinit; + r.init = init; + r.onevent = onevent; + r.noconcurrency = noconcurrency ? 1 : 0; +#if AFB_BINDING_VERSION >= 3 + r.userdata = userdata; +#endif + return r; +}; + +/*************************************************************************/ +/*** E N D ***/ +/*************************************************************************/ +} -- cgit 1.2.3-korg