diff options
author | Jose Bollo <jose.bollo@iot.bzh> | 2019-04-12 11:18:46 +0200 |
---|---|---|
committer | José Bollo <jose.bollo@iot.bzh> | 2019-04-23 11:22:09 +0200 |
commit | 6401efb14339925e696a65eea8e8548f1fddf3ba (patch) | |
tree | fea29c2a65862419572aaaa2a8e66554a7d3589e | |
parent | 13457f6458e1f604e437ce7a9a680c8703078fbf (diff) |
binding-wrap: Rework of context handling
The C++ wrapper for handling contexts has
to be improved. This is a proposition of
improvement.
Change-Id: I7df36383f427d109356bdf4df573cba4b6e6ec05
Signed-off-by: Jose Bollo <jose.bollo@iot.bzh>
-rw-r--r-- | bindings/tutorials/tuto-3.cpp | 45 | ||||
-rw-r--r-- | include/afb/c++/binding-wrap.hpp | 60 |
2 files changed, 72 insertions, 33 deletions
diff --git a/bindings/tutorials/tuto-3.cpp b/bindings/tutorials/tuto-3.cpp index 8ad69ef3..a257999b 100644 --- a/bindings/tutorials/tuto-3.cpp +++ b/bindings/tutorials/tuto-3.cpp @@ -1,3 +1,5 @@ +#include <string> + #include <string.h> #include <json-c/json.h> @@ -6,10 +8,20 @@ afb::event event_login, event_logout; +class session +{ +private: + std::string user_; +public: + session(const char *user) : user_(user) {} + ~session() {} + operator const char *() const { return user_.c_str(); } +}; + void login(afb::req req) { json_object *args, *user, *passwd; - char *usr; + const char *usr; args = req.json(); if (!json_object_object_get_ex(args, "user", &user) @@ -23,10 +35,10 @@ void login(afb::req req) AFB_REQ_ERROR(req, "login, unauthorized: %s", json_object_get_string(args)); req.fail("unauthorized"); } else { - usr = strdup(json_object_get_string(user)); + usr = json_object_get_string(user); AFB_REQ_NOTICE(req, "login user: %s", usr); + req.context<session>().set(new session(usr)); req.session_set_LOA(1); -// req.context(1, nullptr, free, usr); req.success(); event_login.push(json_object_new_string(usr)); } @@ -35,19 +47,17 @@ void login(afb::req req) void action(afb::req req) { json_object *args, *val; - char *usr; + session &usr = req.context<session>(); args = req.json(); -// usr = (char*)req.context_get(); -usr = nullptr; - AFB_REQ_NOTICE(req, "action for user %s: %s", usr, json_object_get_string(args)); + AFB_REQ_NOTICE(req, "action for user %s: %s", (const char*)usr, json_object_get_string(args)); if (json_object_object_get_ex(args, "subscribe", &val)) { if (json_object_get_boolean(val)) { - AFB_REQ_NOTICE(req, "user %s subscribes to events", usr); + AFB_REQ_NOTICE(req, "user %s subscribes to events", (const char*)usr); req.subscribe(event_login); req.subscribe(event_logout); } else { - AFB_REQ_NOTICE(req, "user %s unsubscribes to events", usr); + AFB_REQ_NOTICE(req, "user %s unsubscribes to events", (const char*)usr); req.unsubscribe(event_login); req.unsubscribe(event_logout); } @@ -57,22 +67,16 @@ usr = nullptr; void logout(afb::req req) { - char *usr; + session &usr = req.context<session>(); -// usr = (char*)req.context_get(); -usr = nullptr; - AFB_REQ_NOTICE(req, "login user %s out", usr); - event_logout.push(json_object_new_string(usr)); + AFB_REQ_NOTICE(req, "login user %s out", (const char*)usr); + event_logout.push(json_object_new_string((const char*)usr)); req.session_set_LOA(0); -// req.context_clear(); + req.context<session>().clear(); req.success(); } -int init( -#if AFB_BINDING_VERSION >= 3 - afb_api_t api -#endif -) +int init(afb_api_t api) { AFB_NOTICE("init"); event_login = afb_daemon_make_event("login"); @@ -92,4 +96,3 @@ const afb_verb_t verbs[] = { const afb_binding_t afbBindingExport = afb::binding("tuto-3", verbs, "third tutorial: C++", init); - diff --git a/include/afb/c++/binding-wrap.hpp b/include/afb/c++/binding-wrap.hpp index a23e5537..6af3f845 100644 --- a/include/afb/c++/binding-wrap.hpp +++ b/include/afb/c++/binding-wrap.hpp @@ -258,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; @@ -294,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_); } }; /*************************************************************************/ @@ -476,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_); } |