diff options
author | Felix Fietkau <nbd@nbd.name> | 2025-01-01 16:26:50 +0100 |
---|---|---|
committer | Felix Fietkau <nbd@nbd.name> | 2025-02-04 13:31:53 +0100 |
commit | f0e865fe3dddb4c6681c7f5be25438f1d0f4ae68 (patch) | |
tree | 6d41a6efe93cdc68b61c047e6702a2b75528d39d /lib | |
parent | 6dd08716205fb974215521fd03ebcaa96c26b031 (diff) |
ubus: add named parameter support in functions with many params
When a function supports many parameters, the order can be somewhat
confusing, especially when dealing with several optional ones.
In order to make this easier to use, support for passing an object with
named parameters.
for example:
obj.notify("test", data, null, null, null, 1000);
can be written as:
obj.notify({
method: "test",
data,
timeout: 1000
});
Signed-off-by: Felix Fietkau <nbd@nbd.name>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/ubus.c | 64 |
1 files changed, 40 insertions, 24 deletions
@@ -23,6 +23,10 @@ #define ok_return(expr) do { set_error(0, NULL); return (expr); } while(0) #define err_return(err, ...) do { set_error(err, __VA_ARGS__); return NULL; } while(0) +#define REQUIRED 0 +#define OPTIONAL 1 +#define NAMED 2 + static struct { enum ubus_msg_status code; char *msg; @@ -62,14 +66,20 @@ _arg_type(uc_type_t type) } static bool -_args_get(uc_vm_t *vm, size_t nargs, ...) +_args_get(uc_vm_t *vm, bool named, size_t nargs, ...) { - uc_value_t **ptr, *arg; + uc_value_t **ptr, *arg, *obj; uc_type_t type, t; const char *name; size_t index = 0; va_list ap; - bool opt; + int opt; + + if (named) { + obj = uc_fn_arg(0); + if (nargs != 1 || ucv_type(obj) != UC_OBJECT) + named = false; + } va_start(ap, nargs); @@ -79,13 +89,18 @@ _args_get(uc_vm_t *vm, size_t nargs, ...) if (!name) break; - arg = uc_fn_arg(index++); - type = va_arg(ap, uc_type_t); opt = va_arg(ap, int); ptr = va_arg(ap, uc_value_t **); - if (!opt && !arg) + if (named) + arg = ucv_object_get(obj, name, NULL); + else if (opt != NAMED) + arg = uc_fn_arg(index++); + else + arg = NULL; + + if (opt == REQUIRED && !arg) err_return(UBUS_STATUS_INVALID_ARGUMENT, "Argument %s is required", name); t = ucv_type(arg); @@ -104,7 +119,8 @@ _args_get(uc_vm_t *vm, size_t nargs, ...) ok_return(true); } -#define args_get(vm, nargs, ...) do { if (!_args_get(vm, nargs, __VA_ARGS__, NULL)) return NULL; } while(0) +#define args_get_named(vm, nargs, ...) do { if (!_args_get(vm, true, nargs, __VA_ARGS__, NULL)) return NULL; } while(0) +#define args_get(vm, nargs, ...) do { if (!_args_get(vm, false, nargs, __VA_ARGS__, NULL)) return NULL; } while(0) static uc_resource_type_t *subscriber_type; static uc_resource_type_t *listener_type; @@ -688,11 +704,11 @@ uc_ubus_call(uc_vm_t *vm, size_t nargs) conn_get(vm, &c); - args_get(vm, nargs, - "object name", UC_STRING, false, &objname, - "function name", UC_STRING, false, &funname, - "function arguments", UC_OBJECT, true, &funargs, - "multiple return", UC_BOOLEAN, true, &mret); + args_get_named(vm, nargs, + "object", UC_STRING, REQUIRED, &objname, + "method", UC_STRING, REQUIRED, &funname, + "data", UC_OBJECT, OPTIONAL, &funargs, + "multiple_return", UC_BOOLEAN, OPTIONAL, &mret); blob_buf_init(&c->buf, 0); @@ -729,11 +745,11 @@ uc_ubus_defer(uc_vm_t *vm, size_t nargs) conn_get(vm, &c); - args_get(vm, nargs, - "object name", UC_STRING, false, &objname, - "function name", UC_STRING, false, &funname, - "function arguments", UC_OBJECT, true, &funargs, - "reply callback", UC_CLOSURE, true, &replycb); + args_get_named(vm, nargs, + "object", UC_STRING, REQUIRED, &objname, + "method", UC_STRING, REQUIRED, &funname, + "data", UC_OBJECT, OPTIONAL, &funargs, + "cb", UC_CLOSURE, OPTIONAL, &replycb); blob_buf_init(&c->buf, 0); @@ -1005,13 +1021,13 @@ uc_ubus_object_notify(uc_vm_t *vm, size_t nargs) if (!uuobj || !*uuobj) err_return(UBUS_STATUS_INVALID_ARGUMENT, "Invalid object context"); - args_get(vm, nargs, - "typename", UC_STRING, false, &typename, - "message", UC_OBJECT, true, &message, - "data callback", UC_CLOSURE, true, &data_cb, - "status callback", UC_CLOSURE, true, &status_cb, - "completion callback", UC_CLOSURE, true, &complete_cb, - "timeout", UC_INTEGER, true, &timeout); + args_get_named(vm, nargs, + "type", UC_STRING, REQUIRED, &typename, + "data", UC_OBJECT, OPTIONAL, &message, + "data_cb", UC_CLOSURE, OPTIONAL, &data_cb, + "status_cb", UC_CLOSURE, OPTIONAL, &status_cb, + "cb", UC_CLOSURE, OPTIONAL, &complete_cb, + "timeout", UC_INTEGER, OPTIONAL, &timeout); t = timeout ? ucv_int64_get(timeout) : -1; |