Update copyright dates
[src/app-framework-binder.git] / include / afb / c++ / binding-wrap.hpp
index 81122cb..a998469 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016-2019 "IoT.bzh"
+ * Copyright (C) 2015-2020 "IoT.bzh"
  * Author: José Bollo <jose.bollo@iot.bzh>
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -42,6 +42,7 @@ namespace afb {
 /* pre-declaration of classes                                            */
 /*************************************************************************/
 
+class api;
 class arg;
 class event;
 class req;
@@ -86,15 +87,104 @@ bool callsync(const char *api, const char *verb, struct json_object *args, struc
 /* effective declaration of classes                                      */
 /*************************************************************************/
 
+/* apis */
+class api
+{
+protected:
+       afb_api_t api_;
+public:
+       using call_cb = void (*)(void *closure, struct json_object *object, const char *error, const char *info, afb_api_t api);
+       using queue_cb = void (*)(int signum, void *arg);
+       using event_cb = void (*)(void *, const char *, struct json_object *, afb_api_t);
+       using preinit_cb = int (*)(void *, afb_api_t);
+       using verb_cb = void (*)(afb_req_t req);
+       using onevent_cb = void (*)(afb_api_t api, const char *event, struct json_object *object);
+       using oninit_cb = int (*)(afb_api_t api);
+
+       api();
+       api(afb_api_t a);
+       api(const api &other) = delete;
+       api(api &&other);
+       ~api();
+       api &operator=(const api &other) = delete;
+       api &operator=(api &&other);
+
+       operator afb_api_t() const;
+       afb_api_t operator->() const;
+
+       /* General functions */
+       const char *name() const;
+       void *get_userdata() const;
+       void set_userdata(void *value) const;
+       int require_api(const char *name, int initialized) const;
+       int require_api(const std::string &name, int initialized) const;
+
+       /* Verbosity functions */
+       int wants_log_level(int level) const;
+       void vverbose(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;
+
+       /* Data retrieval functions */
+       int rootdir_get_fd() const;
+       int rootdir_open_locale(const char *filename, int flags, const char *locale) const;
+       int rootdir_open_locale(const std::string &filename, int flags, const std::string &locale) const;
+       struct json_object *settings() const;
+
+       /* Calls and job functions */
+       void call(const char *apiname, const char *verb, struct json_object *args, call_cb callback, void *closure) const;
+       void call(const std::string &apiname, const std::string &verb, struct json_object *args, call_cb callback, void *closure) const;
+       int call_sync(const char *apiname, const char *verb, struct json_object *args, struct json_object **object, char **error, char **info) const;
+       int call_sync(const std::string &apiname, const std::string &verb, struct json_object *args, struct json_object **object, std::string &error, std::string &info) const;
+       int queue_job(queue_cb callback, void *argument, void *group, int timeout) const;
+
+       /* Event functions */
+       int broadcast_event(const char *name, struct json_object *object) const;
+       int broadcast_event(const std::string &name, struct json_object *object) const;
+       event make_event(const char *name) const;
+       event make_event(const std::string &name) const;
+       int event_handler_add(const char *pattern, event_cb callback, void *closure) const;
+       int event_handler_add(const std::string &pattern, event_cb callback, void *closure) const;
+       int event_handler_del(const char *pattern, void **closure) const;
+       int event_handler_del(const std::string &pattern, void **closure) const;
+
+       /* Systemd functions */
+       struct sd_event *get_event_loop() const;
+       struct sd_bus *get_user_bus() const;
+       struct sd_bus *get_system_bus() const;
+
+       /* Dynamic api functions */
+       api new_api(const char *apiname, const char *info, int noconcurrency, preinit_cb preinit, void *closure) const;
+       api new_api(const std::string &apiname, const std::string &info, int noconcurrency, preinit_cb preinit, void *closure) const;
+       int set_verbs(const struct afb_verb_v2 *verbs) const;
+       int set_verbs(const struct afb_verb_v3 *verbs) const;
+       int add_verb(const char *verb, const char *info, verb_cb callback, void *vcbdata, const struct afb_auth *auth, uint32_t session, int glob) const;
+       int add_verb(const std::string &verb, const std::string &info, verb_cb callback, void *vcbdata, const struct afb_auth *auth, uint32_t session, int glob) const;
+       int del_verb(const char *verb, void **vcbdata) const;
+       int del_verb(const std::string &verb, void **vcbdata) const;
+       int on_event(onevent_cb onevent) const;
+       int on_init(oninit_cb oninit) const;
+       int provide_class(const char *name) const;
+       int provide_class(const std::string &name) const;
+       int require_class(const char *name) const;
+       int require_class(const std::string &name) const;
+       void seal() const;
+       int delete_api() const;
+       int add_alias(const char *name, const char *as_name) const;
+       int add_alias(const std::string &name, const std::string &as_name) const;
+};
+
 /* events */
 class event
 {
        afb_event_t event_;
 public:
-       event() { invalidate(); }
+       event();
        event(afb_event_t e);
        event(const event &other);
+       event(event &&other);
+       ~event();
        event &operator=(const event &other);
+       event &operator=(event &&other);
 
        operator afb_event_t() const;
        afb_event_t operator->() const;
@@ -102,8 +192,6 @@ public:
        operator bool() const;
        bool is_valid() const;
 
-       void invalidate();
-
        int broadcast(json_object *object) const;
        int push(json_object *object) const;
 
@@ -170,8 +258,6 @@ public:
        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;
@@ -206,6 +292,54 @@ public:
        int get_uid() const;
 
        json_object *get_client_info() const;
+
+       template < class T = void >
+       class contextclass {
+
+               friend class req;
+               afb_req_t req_;
+               contextclass(afb_req_t r) : req_(r) {}
+
+       public:
+               inline operator T *() const { return get(); }
+               inline operator T &() const { return *get(); }
+               inline T* get() const {
+                       return reinterpret_cast<T*>(
+                               afb_req_context(req_, 0,
+                                       nullptr,
+                                       nullptr,
+                                       nullptr));
+               }
+
+               inline void set(T *value, void (*destroyer)(T*) = [](T*t){delete t;}) const {
+                       afb_req_context(req_, 1,
+                               nullptr,
+                               reinterpret_cast<void(*)(void*)>(destroyer),
+                               reinterpret_cast<void*>(value));
+               }
+
+               inline void unset() { set(nullptr); }
+               inline void clear() { set(nullptr); }
+
+               inline T *lazy(T *(*allocator)() = []()->T*{return new T();}, void (*destroyer)(T*) = [](T*t){delete t;}) const {
+                       return reinterpret_cast<T*>(
+                               afb_req_context(req_, 0,
+                                       [allocator](void*)->T*{return allocator();},
+                                       reinterpret_cast<void(*)(void*)>(destroyer),
+                                       nullptr));
+               }
+
+               template <class I>
+               inline T *lazy(I *i, T *(*allocator)(I*) = [](I*i)->T*{return new T(i);}, void (*destroyer)(T*) = [](T*t){delete t;}) const {
+                       return reinterpret_cast<T*>(
+                               afb_req_context(req_, 0,
+                                       [allocator](void*i)->T*{return allocator(reinterpret_cast<I*>(i));},
+                                       reinterpret_cast<void(*)(void*)>(destroyer),
+                                       reinterpret_cast<void*>(i)));
+               }
+       };
+
+       template < class T > contextclass<T> context() const { return contextclass<T>(req_); }
 };
 
 /*************************************************************************/
@@ -233,10 +367,82 @@ public:
 /* effective declaration of classes                                      */
 /*************************************************************************/
 
+/* apis */
+inline api::api() : api_{nullptr} { }
+inline api::api(afb_api_t a) : api_{a} { }
+inline api::api(api &&other) : api_{other.api_} { other.api_ = nullptr; }
+inline api::~api() { api_ = nullptr; }
+inline api &api::operator=(api &&other) { api_ = other.api_; other.api_ = nullptr; return *this;}
+inline api::operator afb_api_t() const { return api_; }
+inline afb_api_t api::operator->() const { return api_; }
+inline const char *api::name() const { return afb_api_name(api_); }
+inline void *api::get_userdata() const { return afb_api_get_userdata(api_); }
+inline void api::set_userdata(void *value) const { afb_api_set_userdata(api_, value); }
+inline int api::require_api(const char *name, int initialized) const { return afb_api_require_api(api_, name, initialized); }
+inline int api::require_api(const std::string& name, int initialized) const { return afb_api_require_api(api_, name.c_str(), initialized); }
+inline int api::wants_log_level(int level) const { return afb_api_wants_log_level(api_, level); }
+inline void api::vverbose(int level, const char *file, int line, const char *func, const char *fmt, va_list args) const { afb_api_vverbose(api_, level, file, line, func, fmt, args); }
+inline void api::verbose(int level, const char *file, int line, const char *func, const char *fmt, ...) const
+{
+       va_list args;
+       va_start(args, fmt);
+       vverbose(level, file, line, func, fmt, args);
+       va_end(args);
+}
+inline int api::rootdir_get_fd() const { return afb_api_rootdir_get_fd(api_); }
+inline int api::rootdir_open_locale(const char *filename, int flags, const char *locale) const { return afb_api_rootdir_open_locale(api_, filename, flags, locale); }
+inline int api::rootdir_open_locale(const std::string &filename, int flags, const std::string &locale) const { return afb_api_rootdir_open_locale(api_, filename.c_str(), flags, locale.c_str()); }
+inline struct json_object *api::settings() const { return afb_api_settings(api_); }
+inline void api::call(const char *apiname, const char *verb, struct json_object *args, call_cb callback, void *closure) const { afb_api_call(api_, apiname, verb, args, callback, closure); }
+inline void api::call(const std::string &apiname, const std::string &verb, struct json_object *args, call_cb callback, void *closure) const { afb_api_call(api_, apiname.c_str(), verb.c_str(), args, callback, closure); }
+inline int api::call_sync(const char *apiname, const char *verb, struct json_object *args, struct json_object **object, char **error, char **info) const { return afb_api_call_sync(api_, apiname, verb, args, object, error, info); }
+inline int api::call_sync(const std::string &apiname, const std::string &verb, struct json_object *args, struct json_object **object, std::string &error, std::string& info) const
+{
+       char *err, *inf;
+       int ret = afb_api_call_sync(api_, apiname.c_str(), verb.c_str(), args, object, &err, &inf);
+       error = err;
+       info = inf;
+       return ret;
+}
+inline int api::queue_job(queue_cb callback, void *argument, void *group, int timeout) const { return afb_api_queue_job(api_, callback, argument, group, timeout); }
+inline int api::broadcast_event(const char *name, struct json_object *object) const { return afb_api_broadcast_event(api_, name, object); }
+inline int api::broadcast_event(const std::string &name, struct json_object *object) const { return afb_api_broadcast_event(api_, name.c_str(), object); }
+inline event api::make_event(const char *name) const { return event(afb_api_make_event(api_, name)); }
+inline event api::make_event(const std::string &name) const { return event(afb_api_make_event(api_, name.c_str())); }
+inline int api::event_handler_add(const char *pattern, event_cb callback, void *closure) const { return afb_api_event_handler_add(api_, pattern, callback, closure); }
+inline int api::event_handler_add(const std::string &pattern, event_cb callback, void *closure) const { return afb_api_event_handler_add(api_, pattern.c_str(), callback, closure); }
+inline int api::event_handler_del(const char *pattern, void **closure) const { return afb_api_event_handler_del(api_, pattern, closure); }
+inline int api::event_handler_del(const std::string &pattern, void **closure) const { return afb_api_event_handler_del(api_, pattern.c_str(), closure); }
+inline struct sd_event *api::get_event_loop() const { return afb_api_get_event_loop(api_); }
+inline struct sd_bus *api::get_user_bus() const { return afb_api_get_user_bus(api_); }
+inline struct sd_bus *api::get_system_bus() const { return afb_api_get_system_bus(api_); }
+inline api api::new_api(const char *apiname, const char *info, int noconcurrency, preinit_cb preinit, void *closure) const { return api(afb_api_new_api(api_, apiname, info, noconcurrency, preinit, closure)); }
+inline api api::new_api(const std::string &apiname, const std::string &info, int noconcurrency, preinit_cb preinit, void *closure) const { return api(afb_api_new_api(api_, apiname.c_str(), info.c_str(), noconcurrency, preinit, closure)); }
+inline int api::set_verbs(const struct afb_verb_v2 *verbs) const { return afb_api_set_verbs_v2(api_, verbs); }
+inline int api::set_verbs(const struct afb_verb_v3 *verbs) const { return afb_api_set_verbs_v3(api_, verbs); }
+inline int api::add_verb(const char *verb, const char *info, verb_cb callback, void *vcbdata, const struct afb_auth *auth, uint32_t session, int glob) const { return afb_api_add_verb(api_, verb, info, callback, vcbdata, auth, session, glob); }
+inline int api::add_verb(const std::string &verb, const std::string &info, verb_cb callback, void *vcbdata, const struct afb_auth *auth, uint32_t session, int glob) const { return afb_api_add_verb(api_, verb.c_str(), info.c_str(), callback, vcbdata, auth, session, glob); }
+inline int api::del_verb(const char *verb, void **vcbdata) const { return afb_api_del_verb(api_, verb, vcbdata); }
+inline int api::del_verb(const std::string &verb, void **vcbdata) const { return afb_api_del_verb(api_, verb.c_str(), vcbdata); }
+inline int api::on_event(onevent_cb onevent) const { return afb_api_on_event(api_, onevent); }
+inline int api::on_init(oninit_cb oninit) const { return afb_api_on_init(api_, oninit); }
+inline int api::provide_class(const char *name) const { return afb_api_provide_class(api_, name); }
+inline int api::provide_class(const std::string &name) const { return afb_api_provide_class(api_, name.c_str()); }
+inline int api::require_class(const char *name) const { return afb_api_require_class(api_, name); }
+inline int api::require_class(const std::string &name) const { return afb_api_require_class(api_, name.c_str()); }
+inline void api::seal() const { afb_api_seal(api_); }
+inline int api::delete_api() const { return afb_api_delete_api(api_); }
+inline int api::add_alias(const char *name, const char *as_name) const { return afb_api_add_alias(api_, name, as_name); }
+inline int api::add_alias(const std::string &name, const std::string &as_name) const { return afb_api_add_alias(api_, name.c_str(), as_name.c_str()); }
+
 /* events */
-inline event::event(afb_event_t e) : event_(e) { }
-inline event::event(const event &other) : event_(other.event_) { }
+inline event::event() : event_{nullptr} { }
+inline event::event(afb_event_t e) : event_{e} { }
+inline event::event(event &&other) : event_{other.event_} { other.event_ = nullptr; }
+inline event::event(const event &other) : event_{other.event_} { addref(); }
+inline event::~event() { unref(); }
 inline event &event::operator=(const event &other) { event_ = other.event_; return *this; }
+inline event &event::operator=(event &&other) { event_ = other.event_; other.event_ = nullptr; return *this;}
 
 inline event::operator afb_event_t() const { return event_; }
 inline afb_event_t event::operator->() const { return event_; }
@@ -244,12 +450,10 @@ 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_); }
 
-inline void event::invalidate() { event_ = nullptr; }
-
 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::unref() { if (event_) { afb_event_unref(event_); } event_ = nullptr; }
 inline void event::addref() { afb_event_addref(event_); }
 inline const char *event::name() const { return afb_event_name(event_); }
 
@@ -270,7 +474,6 @@ 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; }
@@ -319,16 +522,6 @@ inline void req::failf(const char *error, const char *info, ...) const
        va_end(args);
 }
 
-template < class T >
-inline T *req::context() const
-{
-       T* (*creater)(void*) = [](){return new T();};
-       void (*freer)(T*) = [](T*t){delete t;};
-       return reinterpret_cast<T*>(afb_req_context(req_, 0,
-                       reinterpret_cast<void *(*)(void*)>(creater),
-                       reinterpret_cast<void (*)(void*)>(freer), nullptr));
-}
-
 inline void req::addref() const { afb_req_addref(req_); }
 
 inline void req::unref() const { afb_req_unref(req_); }
@@ -474,28 +667,28 @@ inline bool callsync(const char *api, const char *verb, struct json_object *args
 
 constexpr afb_auth auth_no()
 {
-       afb_auth r = { afb_auth_No, 0, 0};
+       afb_auth r = { afb_auth_No, {0}, nullptr};
        r.type = afb_auth_No;
        return r;
 }
 
 constexpr afb_auth auth_yes()
 {
-       afb_auth r = { afb_auth_No, 0, 0};
+       afb_auth r = { afb_auth_No, {0}, nullptr};
        r.type = afb_auth_Yes;
        return r;
 }
 
 constexpr afb_auth auth_token()
 {
-       afb_auth r = { afb_auth_No, 0, 0};
+       afb_auth r = { afb_auth_No, {0}, nullptr};
        r.type = afb_auth_Token;
        return r;
 }
 
 constexpr afb_auth auth_LOA(unsigned loa)
 {
-       afb_auth r = { afb_auth_No, 0, 0};
+       afb_auth r = { afb_auth_No, {0}, nullptr};
        r.type = afb_auth_LOA;
        r.loa = loa;
        return r;
@@ -503,7 +696,7 @@ constexpr afb_auth auth_LOA(unsigned loa)
 
 constexpr afb_auth auth_permission(const char *permission)
 {
-       afb_auth r = { afb_auth_No, 0, 0};
+       afb_auth r = { afb_auth_No, {0}, nullptr};
        r.type = afb_auth_Permission;
        r.text = permission;
        return r;
@@ -511,7 +704,7 @@ constexpr afb_auth auth_permission(const char *permission)
 
 constexpr afb_auth auth_not(const afb_auth *other)
 {
-       afb_auth r = { afb_auth_No, 0, 0};
+       afb_auth r = { afb_auth_No, {0}, nullptr};
        r.type = afb_auth_Not;
        r.first = other;
        return r;
@@ -524,7 +717,7 @@ constexpr afb_auth auth_not(const afb_auth &other)
 
 constexpr afb_auth auth_or(const afb_auth *first, const afb_auth *next)
 {
-       afb_auth r = { afb_auth_No, 0, 0};
+       afb_auth r = { afb_auth_No, {0}, nullptr};
        r.type = afb_auth_Or;
        r.first = first;
        r.next = next;
@@ -538,7 +731,7 @@ constexpr afb_auth auth_or(const afb_auth &first, const afb_auth &next)
 
 constexpr afb_auth auth_and(const afb_auth *first, const afb_auth *next)
 {
-       afb_auth r = { afb_auth_No, 0, 0};
+       afb_auth r = { afb_auth_No, {0}, nullptr};
        r.type = afb_auth_And;
        r.first = first;
        r.next = next;
@@ -560,15 +753,7 @@ constexpr afb_verb_t verb(
        void *vcbdata = nullptr
 )
 {
-       afb_verb_t r = { 0, 0, 0, 0, 0, 0, 0 };
-       r.verb = name;
-       r.callback = callback;
-       r.info = info;
-       r.session = session;
-       r.auth = auth;
-       r.glob = (unsigned)glob;
-       r.vcbdata = vcbdata;
-       return r;
+       return { name, callback, auth, info, vcbdata, session, glob };
 }
 
 void __attribute__((weak)) __afb__verb__cb__for__global__(afb_req_t r)
@@ -583,12 +768,11 @@ void __attribute__((weak)) __afb__verb__cb__for__global__(afb_req_t r)
 
 constexpr afb_verb_t verb(
        const char *name,
-       void (&callback)(req),
+       void (*callback)(req),
        const char *info = nullptr,
        uint16_t session = 0,
        const afb_auth *auth = nullptr,
-       bool glob = false,
-       void *vcbdata = nullptr
+       bool glob = false
 )
 {
        return verb(
@@ -604,8 +788,7 @@ constexpr afb_verb_t verb(
 
 constexpr afb_verb_t verbend()
 {
-       afb_verb_t r = verb(nullptr, nullptr);
-       return r;
+       return { 0, 0, 0, 0, 0, 0, 0 };
 }
 
 constexpr afb_binding_t binding(
@@ -620,17 +803,9 @@ constexpr afb_binding_t binding(
        void *userdata = nullptr
 )
 {
-       afb_binding_t r = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-       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;
-       r.userdata = userdata;
-       return r;
+       return {
+               name, specification, info, verbs, preinit, init, onevent, userdata,
+               nullptr, nullptr, nullptr, static_cast<unsigned int>(noconcurrency) };
 };
 
 /*************************************************************************/