c++: Reworked the event class
[src/app-framework-binder.git] / include / afb / c++ / binding-wrap.hpp
1 /*
2  * Copyright (C) 2016-2019 "IoT.bzh"
3  * Author: José Bollo <jose.bollo@iot.bzh>
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *   http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 #pragma once
19
20 #include <cstddef>
21 #include <cstdlib>
22 #include <cstdarg>
23 #include <functional>
24
25 /* ensure version */
26 #ifndef AFB_BINDING_VERSION
27 # define AFB_BINDING_VERSION   3
28 #endif
29
30 /* check the version */
31 #if AFB_BINDING_VERSION < 3
32 # error "AFB_BINDING_VERSION must be at least 3"
33 #endif
34
35 /* get C definitions of bindings */
36 extern "C" {
37 #include <afb/afb-binding.h>
38 }
39
40 namespace afb {
41 /*************************************************************************/
42 /* pre-declaration of classes                                            */
43 /*************************************************************************/
44
45 class arg;
46 class event;
47 class req;
48
49 /*************************************************************************/
50 /* declaration of functions                                              */
51 /*************************************************************************/
52
53 int broadcast_event(const char *name, json_object *object = nullptr);
54
55 event make_event(const char *name);
56
57 void verbose(int level, const char *file, int line, const char * func, const char *fmt, va_list args);
58
59 void verbose(int level, const char *file, int line, const char * func, const char *fmt, ...);
60
61 int rootdir_get_fd();
62
63 int rootdir_open_locale_fd(const char *filename, int flags, const char *locale = nullptr);
64
65 int queue_job(void (*callback)(int signum, void *arg), void *argument, void *group, int timeout);
66
67 int require_api(const char *apiname, bool initialized = true);
68
69 int add_alias(const char *apiname, const char *aliasname);
70
71 int verbosity();
72
73 bool wants_errors();
74 bool wants_warnings();
75 bool wants_notices();
76 bool wants_infos();
77 bool wants_debugs();
78
79 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);
80
81 template <class T> 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);
82
83 bool callsync(const char *api, const char *verb, struct json_object *args, struct json_object *&result);
84
85 /*************************************************************************/
86 /* effective declaration of classes                                      */
87 /*************************************************************************/
88
89 /* events */
90 class event
91 {
92         afb_event_t event_;
93 public:
94         event();
95         event(afb_event_t e);
96         event(const event &other);
97         event(event &&other);
98         ~event();
99         event &operator=(const event &other);
100         event &operator=(event &&other);
101
102         operator afb_event_t() const;
103         afb_event_t operator->() const;
104
105         operator bool() const;
106         bool is_valid() const;
107
108         int broadcast(json_object *object) const;
109         int push(json_object *object) const;
110
111         void unref();
112         void addref();
113         const char *name() const;
114 };
115
116 /* args */
117 class arg
118 {
119         struct afb_arg arg_;
120 public:
121         arg() = delete;
122         arg(const struct afb_arg &a);
123         arg(const arg &other);
124         arg &operator=(const arg &other);
125
126         operator const struct afb_arg&() const;
127
128         bool has_name() const;
129         bool has_value() const;
130         bool has_path() const;
131
132         const char *name() const;
133         const char *value() const;
134         const char *path() const;
135 };
136
137 /* req(uest) */
138 class req
139 {
140         afb_req_t req_;
141
142 public:
143         req() = delete;
144         req(afb_req_t r);
145         req(const req &other);
146         req &operator=(const req &other);
147
148         operator afb_req_t() const;
149         afb_req_t operator->() const;
150
151         operator bool() const;
152         bool is_valid() const;
153
154         arg get(const char *name) const;
155
156         const char *value(const char *name) const;
157
158         const char *path(const char *name) const;
159
160         json_object *json() const;
161
162         void reply(json_object *obj = nullptr, const char *error = nullptr, const char *info = nullptr) const;
163         void replyf(json_object *obj, const char *error, const char *info, ...) const;
164         void replyv(json_object *obj, const char *error, const char *info, va_list args) const;
165
166         void success(json_object *obj = nullptr, const char *info = nullptr) const;
167         void successf(json_object *obj, const char *info, ...) const;
168         void successv(json_object *obj, const char *info, va_list args) const;
169
170         void fail(const char *error = "failed", const char *info = nullptr) const;
171         void failf(const char *error, const char *info, ...) const;
172         void failv(const char *error, const char *info, va_list args) const;
173
174         template < class T > T *context() const;
175
176         void addref() const;
177
178         void unref() const;
179
180         void session_close() const;
181
182         bool session_set_LOA(unsigned level) const;
183
184         bool subscribe(const event &event) const;
185
186         bool unsubscribe(const event &event) const;
187
188         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;
189         template <class T> 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;
190
191         bool subcallsync(const char *api, const char *verb, json_object *args, struct json_object *&result) const;
192
193         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;
194
195         template <class T> 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;
196
197         bool subcallsync(const char *api, const char *verb, json_object *args, int flags, struct json_object *&object, char *&error, char *&info) const;
198
199         void verbose(int level, const char *file, int line, const char * func, const char *fmt, va_list args) const;
200
201         void verbose(int level, const char *file, int line, const char * func, const char *fmt, ...) const;
202
203         bool has_permission(const char *permission) const;
204
205         char *get_application_id() const;
206
207         int get_uid() const;
208
209         json_object *get_client_info() const;
210 };
211
212 /*************************************************************************/
213 /* effective declaration of classes                                      */
214 /*************************************************************************/
215 /////////////////////////////////////////////////////////////////////////////////////////////////////
216 /////////////////////////////////////////////////////////////////////////////////////////////////////
217 /////////////////////////////////////////////////////////////////////////////////////////////////////
218 /////////////////////////////////////////////////////////////////////////////////////////////////////
219 /////////////////////////////////////////////////////////////////////////////////////////////////////
220 /////////////////////////////////////////////////////////////////////////////////////////////////////
221 /////////////////////////////////////////////////////////////////////////////////////////////////////
222 /////////////////////////////////////////////////////////////////////////////////////////////////////
223 /////////////////////////////////////////////////////////////////////////////////////////////////////
224 /////////////////////////////////////////////////////////////////////////////////////////////////////
225 /////////////////////////////////////////////////////////////////////////////////////////////////////
226 /////////////////////////////////////////////////////////////////////////////////////////////////////
227 /////////////////////////////////////////////////////////////////////////////////////////////////////
228 /////////////////////////////////////////////////////////////////////////////////////////////////////
229 /////////////////////////////////////////////////////////////////////////////////////////////////////
230 /////////////////////////////////////////////////////////////////////////////////////////////////////
231
232
233 /*************************************************************************/
234 /* effective declaration of classes                                      */
235 /*************************************************************************/
236
237 /* events */
238 inline event::event() : event_{nullptr} { }
239 inline event::event(afb_event_t e) : event_{e} { }
240 inline event::event(event &&other) : event_{other.event_} { other.event_ = nullptr; }
241 inline event::event(const event &other) : event_{other.event_} { addref(); }
242 inline event::~event() { unref(); }
243 inline event &event::operator=(const event &other) { event_ = other.event_; return *this; }
244 inline event &event::operator=(event &&other) { event_ = other.event_; other.event_ = nullptr; return *this;}
245
246 inline event::operator afb_event_t() const { return event_; }
247 inline afb_event_t event::operator->() const { return event_; }
248
249 inline event::operator bool() const { return is_valid(); }
250 inline bool event::is_valid() const { return afb_event_is_valid(event_); }
251
252 inline int event::broadcast(json_object *object) const { return afb_event_broadcast(event_, object); }
253 inline int event::push(json_object *object) const { return afb_event_push(event_, object); }
254
255 inline void event::unref() { if (event_) { afb_event_unref(event_); } event_ = nullptr; }
256 inline void event::addref() { afb_event_addref(event_); }
257 inline const char *event::name() const { return afb_event_name(event_); }
258
259 /* args */
260 inline arg::arg(const struct afb_arg &a) : arg_(a) {}
261 inline arg::arg(const arg &other) : arg_(other.arg_) {}
262 inline arg &arg::operator=(const arg &other) { arg_ = other.arg_; return *this; }
263
264 inline arg::operator const struct afb_arg&() const { return arg_; }
265
266 inline bool arg::has_name() const { return !!arg_.name; }
267 inline bool arg::has_value() const { return !!arg_.value; }
268 inline bool arg::has_path() const { return !!arg_.path; }
269
270 inline const char *arg::name() const { return arg_.name; }
271 inline const char *arg::value() const { return arg_.value; }
272 inline const char *arg::path() const { return arg_.path; }
273
274 /* req(uests)s */
275
276
277 inline req::req(afb_req_t r) : req_(r) {}
278 inline req::req(const req &other) : req_(other.req_) {}
279 inline req &req::operator=(const req &other) { req_ = other.req_; return *this; }
280
281 inline req::operator afb_req_t() const { return req_; }
282 inline afb_req_t req::operator->() const { return req_; }
283
284 inline req::operator bool() const { return is_valid(); }
285 inline bool req::is_valid() const { return afb_req_is_valid(req_); }
286
287 inline arg req::get(const char *name) const { return arg(afb_req_get(req_, name)); }
288
289 inline const char *req::value(const char *name) const { return afb_req_value(req_, name); }
290
291 inline const char *req::path(const char *name) const { return afb_req_path(req_, name); }
292
293 inline json_object *req::json() const { return afb_req_json(req_); }
294
295 inline void req::reply(json_object *obj, const char *error, const char *info) const { afb_req_reply(req_, obj, error, info); }
296 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); }
297 inline void req::replyf(json_object *obj, const char *error, const char *info, ...) const
298 {
299         va_list args;
300         va_start(args, info);
301         replyv(obj, error, info, args);
302         va_end(args);
303 }
304
305 inline void req::success(json_object *obj, const char *info) const { reply(obj, nullptr, info); }
306 inline void req::successv(json_object *obj, const char *info, va_list args) const { replyv(obj, nullptr, info, args); }
307 inline void req::successf(json_object *obj, const char *info, ...) const
308 {
309         va_list args;
310         va_start(args, info);
311         successv(obj, info, args);
312         va_end(args);
313 }
314
315 inline void req::fail(const char *error, const char *info) const { reply(nullptr, error, info); }
316 inline void req::failv(const char *error, const char *info, va_list args) const { replyv(nullptr, error, info, args); }
317 inline void req::failf(const char *error, const char *info, ...) const
318 {
319         va_list args;
320         va_start(args, info);
321         failv(error, info, args);
322         va_end(args);
323 }
324
325 template < class T >
326 inline T *req::context() const
327 {
328         T* (*creater)(void*) = [](){return new T();};
329         void (*freer)(T*) = [](T*t){delete t;};
330         return reinterpret_cast<T*>(afb_req_context(req_, 0,
331                         reinterpret_cast<void *(*)(void*)>(creater),
332                         reinterpret_cast<void (*)(void*)>(freer), nullptr));
333 }
334
335 inline void req::addref() const { afb_req_addref(req_); }
336
337 inline void req::unref() const { afb_req_unref(req_); }
338
339 inline void req::session_close() const { afb_req_session_close(req_); }
340
341 inline bool req::session_set_LOA(unsigned level) const { return !afb_req_session_set_LOA(req_, level); }
342
343 inline bool req::subscribe(const event &event) const { return !afb_req_subscribe(req_, event); }
344
345 inline bool req::unsubscribe(const event &event) const { return !afb_req_unsubscribe(req_, event); }
346
347 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
348 {
349         afb_req_subcall(req_, api, verb, args, flags, callback, closure);
350 }
351
352 template <class T>
353 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
354 {
355         subcall(api, verb, args, flags, reinterpret_cast<void(*)(void*,json_object*,const char*,const char*,afb_req_t)>(callback), reinterpret_cast<void*>(closure));
356 }
357
358 inline bool req::subcallsync(const char *api, const char *verb, json_object *args, int flags, struct json_object *&object, char *&error, char *&info) const
359 {
360         return !afb_req_subcall_sync(req_, api, verb, args, flags, &object, &error, &info);
361 }
362
363 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
364 {
365         afb_req_subcall_legacy(req_, api, verb, args, callback, closure);
366 }
367
368 template <class T>
369 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
370 {
371         subcall(api, verb, args, reinterpret_cast<void(*)(void*,int,json_object*,afb_req_t)>(callback), reinterpret_cast<void*>(closure));
372 }
373
374 inline bool req::subcallsync(const char *api, const char *verb, json_object *args, struct json_object *&result) const
375 {
376         return !afb_req_subcall_sync_legacy(req_, api, verb, args, &result);
377 }
378
379 inline void req::verbose(int level, const char *file, int line, const char * func, const char *fmt, va_list args) const
380 {
381         afb_req_verbose(req_, level, file, line, func, fmt, args);
382 }
383
384 inline void req::verbose(int level, const char *file, int line, const char * func, const char *fmt, ...) const
385 {
386         va_list args;
387         va_start(args, fmt);
388         afb_req_verbose(req_, level, file, line, func, fmt, args);
389         va_end(args);
390 }
391
392 inline bool req::has_permission(const char *permission) const
393 {
394         return bool(afb_req_has_permission(req_, permission));
395 }
396
397 inline char *req::get_application_id() const
398 {
399         return afb_req_get_application_id(req_);
400 }
401
402 inline int req::get_uid() const
403 {
404         return afb_req_get_uid(req_);
405 }
406
407 inline json_object *req::get_client_info() const
408 {
409         return afb_req_get_client_info(req_);
410 }
411
412 /* commons */
413 inline int broadcast_event(const char *name, json_object *object)
414         { return afb_daemon_broadcast_event(name, object); }
415
416 inline event make_event(const char *name)
417         { return afb_daemon_make_event(name); }
418
419 inline void verbose(int level, const char *file, int line, const char * func, const char *fmt, va_list args)
420         { afb_daemon_verbose(level, file, line, func, fmt, args); }
421
422 inline void verbose(int level, const char *file, int line, const char * func, const char *fmt, ...)
423         { va_list args; va_start(args, fmt); verbose(level, file, line, func, fmt, args); va_end(args); }
424
425 inline int rootdir_get_fd()
426         { return afb_daemon_rootdir_get_fd(); }
427
428 inline int rootdir_open_locale_fd(const char *filename, int flags, const char *locale)
429         { return afb_daemon_rootdir_open_locale(filename, flags, locale); }
430
431 inline int queue_job(void (*callback)(int signum, void *arg), void *argument, void *group, int timeout)
432         { return afb_daemon_queue_job(callback, argument, group, timeout); }
433
434 inline int require_api(const char *apiname, bool initialized)
435         { return afb_daemon_require_api(apiname, int(initialized)); }
436
437 inline int add_alias(const char *apiname, const char *aliasname)
438         { return afb_daemon_add_alias(apiname, aliasname); }
439
440 inline int logmask()
441         { return afb_get_logmask(); }
442
443 inline bool wants_errors()
444         { return AFB_SYSLOG_MASK_WANT_ERROR(logmask()); }
445
446 inline bool wants_warnings()
447         { return AFB_SYSLOG_MASK_WANT_WARNING(logmask()); }
448
449 inline bool wants_notices()
450         { return AFB_SYSLOG_MASK_WANT_NOTICE(logmask()); }
451
452 inline bool wants_infos()
453         { return AFB_SYSLOG_MASK_WANT_INFO(logmask()); }
454
455 inline bool wants_debugs()
456         { return AFB_SYSLOG_MASK_WANT_DEBUG(logmask()); }
457
458 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)
459 {
460         afb_service_call(api, verb, args, callback, closure);
461 }
462
463 template <class T>
464 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)
465 {
466         afb_service_call(api, verb, args, reinterpret_cast<void(*)(void*,json_object*,const char*, const char*,afb_api_t)>(callback), reinterpret_cast<void*>(closure));
467 }
468
469 inline bool callsync(const char *api, const char *verb, struct json_object *args, struct json_object *&result, char *&error, char *&info)
470 {
471         return !!afb_service_call_sync(api, verb, args, &result, &error, &info);
472 }
473
474 /*************************************************************************/
475 /* declaration of the binding's authorization s                          */
476 /*************************************************************************/
477
478 constexpr afb_auth auth_no()
479 {
480         afb_auth r = { afb_auth_No, 0, 0};
481         r.type = afb_auth_No;
482         return r;
483 }
484
485 constexpr afb_auth auth_yes()
486 {
487         afb_auth r = { afb_auth_No, 0, 0};
488         r.type = afb_auth_Yes;
489         return r;
490 }
491
492 constexpr afb_auth auth_token()
493 {
494         afb_auth r = { afb_auth_No, 0, 0};
495         r.type = afb_auth_Token;
496         return r;
497 }
498
499 constexpr afb_auth auth_LOA(unsigned loa)
500 {
501         afb_auth r = { afb_auth_No, 0, 0};
502         r.type = afb_auth_LOA;
503         r.loa = loa;
504         return r;
505 }
506
507 constexpr afb_auth auth_permission(const char *permission)
508 {
509         afb_auth r = { afb_auth_No, 0, 0};
510         r.type = afb_auth_Permission;
511         r.text = permission;
512         return r;
513 }
514
515 constexpr afb_auth auth_not(const afb_auth *other)
516 {
517         afb_auth r = { afb_auth_No, 0, 0};
518         r.type = afb_auth_Not;
519         r.first = other;
520         return r;
521 }
522
523 constexpr afb_auth auth_not(const afb_auth &other)
524 {
525         return auth_not(&other);
526 }
527
528 constexpr afb_auth auth_or(const afb_auth *first, const afb_auth *next)
529 {
530         afb_auth r = { afb_auth_No, 0, 0};
531         r.type = afb_auth_Or;
532         r.first = first;
533         r.next = next;
534         return r;
535 }
536
537 constexpr afb_auth auth_or(const afb_auth &first, const afb_auth &next)
538 {
539         return auth_or(&first, &next);
540 }
541
542 constexpr afb_auth auth_and(const afb_auth *first, const afb_auth *next)
543 {
544         afb_auth r = { afb_auth_No, 0, 0};
545         r.type = afb_auth_And;
546         r.first = first;
547         r.next = next;
548         return r;
549 }
550
551 constexpr afb_auth auth_and(const afb_auth &first, const afb_auth &next)
552 {
553         return auth_and(&first, &next);
554 }
555
556 constexpr afb_verb_t verb(
557         const char *name,
558         void (*callback)(afb_req_t),
559         const char *info = nullptr,
560         uint16_t session = 0,
561         const afb_auth *auth = nullptr,
562         bool glob = false,
563         void *vcbdata = nullptr
564 )
565 {
566         afb_verb_t r = { 0, 0, 0, 0, 0, 0, 0 };
567         r.verb = name;
568         r.callback = callback;
569         r.info = info;
570         r.session = session;
571         r.auth = auth;
572         r.glob = (unsigned)glob;
573         r.vcbdata = vcbdata;
574         return r;
575 }
576
577 void __attribute__((weak)) __afb__verb__cb__for__global__(afb_req_t r)
578 {
579         void *vcbdata;
580         void (*callback)(req);
581
582         vcbdata = afb_req_get_vcbdata(r);
583         callback = reinterpret_cast<void(*)(req)>(vcbdata);
584         callback(req(r));
585 }
586
587 constexpr afb_verb_t verb(
588         const char *name,
589         void (&callback)(req),
590         const char *info = nullptr,
591         uint16_t session = 0,
592         const afb_auth *auth = nullptr,
593         bool glob = false,
594         void *vcbdata = nullptr
595 )
596 {
597         return verb(
598                 name,
599                 __afb__verb__cb__for__global__,
600                 info,
601                 session,
602                 auth,
603                 glob,
604                 (void*)(&callback)
605         );
606 }
607
608 constexpr afb_verb_t verbend()
609 {
610         afb_verb_t r = verb(nullptr, nullptr);
611         return r;
612 }
613
614 constexpr afb_binding_t binding(
615         const char *name,
616         const afb_verb_t *verbs,
617         const char *info = nullptr,
618         int (*init)(afb_api_t) = nullptr,
619         const char *specification = nullptr,
620         void (*onevent)(afb_api_t, const char*, struct json_object*) = nullptr,
621         bool noconcurrency = false,
622         int (*preinit)(afb_api_t) = nullptr,
623         void *userdata = nullptr
624 )
625 {
626         afb_binding_t r = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
627         r.api = name;
628         r.specification = specification;
629         r.info = info;
630         r.verbs = verbs;
631         r.preinit = preinit;
632         r.init = init;
633         r.onevent = onevent;
634         r.noconcurrency = noconcurrency ? 1 : 0;
635         r.userdata = userdata;
636         return r;
637 };
638
639 /*************************************************************************/
640 /***                         E N D                                     ***/
641 /*************************************************************************/
642 }