From 06a9f71b1eef89d0a417e465d87be99fad1d7683 Mon Sep 17 00:00:00 2001 From: cpq Date: Sat, 18 Apr 2026 05:39:42 +0100 Subject: [PATCH] Change signature --- mongoose.h | 95 ++++++++++++++++++++++-------------------------------- src/dash.h | 95 ++++++++++++++++++++++-------------------------------- 2 files changed, 76 insertions(+), 114 deletions(-) diff --git a/mongoose.h b/mongoose.h index 3a5b85cc..14e2107f 100644 --- a/mongoose.h +++ b/mongoose.h @@ -3140,28 +3140,21 @@ void mg_rpc_list(struct mg_rpc_req *r); -enum mg_val_type { MG_VAL_INT, MG_VAL_BOOL, MG_VAL_DBL, MG_VAL_STR }; +enum mg_val_type { MG_VAL_INT, MG_VAL_BOOL, MG_VAL_DBL, MG_VAL_STR, MG_VAL_FN }; union mg_val { int i; bool b; double d; struct mg_str s; + void (*fn)(void); }; struct mg_field { const char *name; enum mg_val_type type; - union mg_val value; -}; - -typedef void (*mg_dash_get_fn)(struct mg_field *); -typedef void (*mg_dash_set_fn)(struct mg_field *); - -struct mg_dash { - struct mg_field *fields; - mg_dash_get_fn get; - mg_dash_set_fn set; + void (*get)(union mg_val *); + void (*set)(const union mg_val *); }; static inline struct mg_str trimq(struct mg_str s) { // Trim double quotes @@ -3218,35 +3211,41 @@ static inline struct mg_field *mg_dash_find_field(struct mg_field *fields, static inline size_t mg_print_field(mg_pfn_t fn, void *arg, va_list *ap) { struct mg_field *f = va_arg(*ap, struct mg_field *); + union mg_val val = {0}; size_t n = 0; + if (f->get) f->get(&val); n += mg_xprintf(fn, arg, "%m:", MG_ESC(f->name)); if (f->type == MG_VAL_BOOL) { - n += mg_xprintf(fn, arg, "%s", f->value.b ? "true" : "false"); + n += mg_xprintf(fn, arg, "%s", val.b ? "true" : "false"); } else if (f->type == MG_VAL_INT) { - n += mg_xprintf(fn, arg, "%d", f->value.i); + n += mg_xprintf(fn, arg, "%d", val.i); } else if (f->type == MG_VAL_DBL) { - n += mg_xprintf(fn, arg, "%g", f->value.d); + n += mg_xprintf(fn, arg, "%g", val.d); } else if (f->type == MG_VAL_STR) { - struct mg_str s = f->value.s; - n += mg_xprintf(fn, arg, "%m", mg_print_esc, s.len, s.buf); + n += mg_xprintf(fn, arg, "%m", mg_print_esc, val.s.len, val.s.buf); + } else if (f->type == MG_VAL_FN) { + n += mg_xprintf(fn, arg, "%M", val.fn); } else { n += mg_xprintf(fn, arg, "null"); } return n; } -static inline bool mg_parse_field(struct mg_str json, struct mg_field *f) { +static inline bool mg_parse_field(struct mg_str json, struct mg_field *f, + union mg_val *val) { bool ok = false; if (f->type == MG_VAL_BOOL) { - ok = mg_json_get_bool(json, "$", &f->value.b); + ok = mg_json_get_bool(json, "$", &val->b); } else if (f->type == MG_VAL_INT) { double d; ok = mg_json_get_num(json, "$", &d); - if (ok) f->value.i = (int) d; + if (ok) val->i = (int) d; } else if (f->type == MG_VAL_DBL) { - ok = mg_json_get_num(json, "$", &f->value.d); + ok = mg_json_get_num(json, "$", &val->d); } else if (f->type == MG_VAL_STR) { - f->value.s = trimq(json); + val->s = trimq(json); + } else if (f->type == MG_VAL_FN) { + val->s = json; } return ok; } @@ -3254,7 +3253,7 @@ static inline bool mg_parse_field(struct mg_str json, struct mg_field *f) { static inline size_t mg_dash_print(mg_pfn_t fn, void *arg, va_list *ap) { struct mg_str *req = va_arg(*ap, struct mg_str *); struct mg_field *fields = va_arg(*ap, struct mg_field *); - mg_dash_get_fn get = va_arg(*ap, mg_dash_get_fn); + // mg_dash_get_fn get = va_arg(*ap, mg_dash_get_fn); struct mg_str name = trimq(mg_json_get_tok(*req, "$.params")); struct mg_field *f = mg_dash_find_field(fields, name); size_t i, n = 0; @@ -3262,15 +3261,12 @@ static inline size_t mg_dash_print(mg_pfn_t fn, void *arg, va_list *ap) { const char *comma = ""; n += mg_xprintf(fn, arg, "{"); for (i = 0; fields[i].name != NULL; i++) { - f = &fields[i]; - if (get) get(f); n += mg_xprintf(fn, arg, "%s", comma); - n += mg_xprintf(fn, arg, "%M", mg_print_field, f); + n += mg_xprintf(fn, arg, "%M", mg_print_field, &fields[i]); comma = ","; } n += mg_xprintf(fn, arg, "}"); } else if (f != NULL) { - if (get) get(f); n += mg_xprintf(fn, arg, "{%M}", mg_print_field, f); } else { n += mg_xprintf(fn, arg, "null"); @@ -3278,58 +3274,43 @@ static inline size_t mg_dash_print(mg_pfn_t fn, void *arg, va_list *ap) { return n; } -static inline bool mg_dash_sync(struct mg_mgr *mgr, struct mg_field *f, - mg_dash_get_fn get) { - union mg_val old_value = f->value; - bool changed = false; - if (get) get(f); - // Strings require special comparison - if (f->type == MG_VAL_STR && mg_strcmp(old_value.s, f->value.s) != 0) { - changed = true; - } else if (memcmp(&f->value, &old_value, sizeof(old_value)) != 0) { - changed = true; - } - if (changed && f != NULL) { +static inline void mg_dash_send_change(struct mg_mgr *mgr, struct mg_field *f) { + if (f != NULL) { mg_dash_broadcast(mgr, "{%m:%m,%m:{%M}}", MG_ESC("method"), MG_ESC("change"), MG_ESC("params"), mg_print_field, f); } - return changed; } -static inline bool mg_dash_apply(struct mg_connection *c, struct mg_str json, - struct mg_field *fields, mg_dash_get_fn get, - mg_dash_set_fn set) { +static inline void mg_dash_apply(struct mg_connection *c, struct mg_str json, + struct mg_field *fields) { struct mg_str key, val; size_t ofs = 0; struct mg_field *f = NULL; - bool changed = false; while ((ofs = mg_json_next(json, ofs, &key, &val)) > 0) { key = trimq(key); - if ((f = mg_dash_find_field(fields, key)) != NULL) { - struct mg_field tmp = *f; - mg_parse_field(val, &tmp); - if (set) set(&tmp); - if (mg_dash_sync(c->mgr, f, get)) changed = true; + if ((f = mg_dash_find_field(fields, key)) != NULL && f->set != NULL) { + union mg_val v = {0}; + mg_parse_field(val, f, &v); + f->set(&v); + mg_dash_send_change(c->mgr, f); break; } else { MG_ERROR(("UNKNOWN FIELD: [%.*s]", key.len, key.buf)); } } - return changed; } static inline void mg_dash_process_msg(struct mg_connection *c, struct mg_ws_message *wm, - struct mg_field *fields, - mg_dash_get_fn get, mg_dash_set_fn set) { + struct mg_field *fields) { struct mg_str req = wm->data; struct mg_str method = trimq(mg_json_get_tok(req, "$.method")); if (mg_match(method, mg_str("get"), NULL)) { - mg_dash_success(c, req, "%M", mg_dash_print, &req, fields, get); + mg_dash_success(c, req, "%M", mg_dash_print, &req, fields); } else if (mg_match(method, mg_str("set"), NULL)) { struct mg_str params = trimq(mg_json_get_tok(req, "$.params")); - bool changed = mg_dash_apply(c, params, fields, get, set); - mg_dash_success(c, req, "%s", changed ? "true" : "false"); + mg_dash_apply(c, params, fields); + mg_dash_success(c, req, "%s", "true"); } else { mg_dash_error(c, req, "%s", "unknown method"); } @@ -3350,12 +3331,12 @@ static inline void mg_dash_ev_handler(struct mg_connection *c, int ev, } } else if (ev == MG_EV_WS_MSG) { // Add this to automatically handle "get" and "set" JSON-RPC calls - struct mg_dash *dash = (struct mg_dash *) c->fn_data; + struct mg_field *fields = (struct mg_field *) c->fn_data; struct mg_ws_message *wm = (struct mg_ws_message *) ev_data; - if (dash == NULL || dash->fields == NULL) { + if (fields == NULL) { mg_dash_error(c, wm->data, "%s", "no fields defined"); } else { - mg_dash_process_msg(c, wm, dash->fields, dash->get, dash->set); + mg_dash_process_msg(c, wm, fields); } } } diff --git a/src/dash.h b/src/dash.h index 50858331..8ba2d8cb 100644 --- a/src/dash.h +++ b/src/dash.h @@ -2,28 +2,21 @@ #include "ws.h" -enum mg_val_type { MG_VAL_INT, MG_VAL_BOOL, MG_VAL_DBL, MG_VAL_STR }; +enum mg_val_type { MG_VAL_INT, MG_VAL_BOOL, MG_VAL_DBL, MG_VAL_STR, MG_VAL_FN }; union mg_val { int i; bool b; double d; struct mg_str s; + void (*fn)(void); }; struct mg_field { const char *name; enum mg_val_type type; - union mg_val value; -}; - -typedef void (*mg_dash_get_fn)(struct mg_field *); -typedef void (*mg_dash_set_fn)(struct mg_field *); - -struct mg_dash { - struct mg_field *fields; - mg_dash_get_fn get; - mg_dash_set_fn set; + void (*get)(union mg_val *); + void (*set)(const union mg_val *); }; static inline struct mg_str trimq(struct mg_str s) { // Trim double quotes @@ -80,35 +73,41 @@ static inline struct mg_field *mg_dash_find_field(struct mg_field *fields, static inline size_t mg_print_field(mg_pfn_t fn, void *arg, va_list *ap) { struct mg_field *f = va_arg(*ap, struct mg_field *); + union mg_val val = {0}; size_t n = 0; + if (f->get) f->get(&val); n += mg_xprintf(fn, arg, "%m:", MG_ESC(f->name)); if (f->type == MG_VAL_BOOL) { - n += mg_xprintf(fn, arg, "%s", f->value.b ? "true" : "false"); + n += mg_xprintf(fn, arg, "%s", val.b ? "true" : "false"); } else if (f->type == MG_VAL_INT) { - n += mg_xprintf(fn, arg, "%d", f->value.i); + n += mg_xprintf(fn, arg, "%d", val.i); } else if (f->type == MG_VAL_DBL) { - n += mg_xprintf(fn, arg, "%g", f->value.d); + n += mg_xprintf(fn, arg, "%g", val.d); } else if (f->type == MG_VAL_STR) { - struct mg_str s = f->value.s; - n += mg_xprintf(fn, arg, "%m", mg_print_esc, s.len, s.buf); + n += mg_xprintf(fn, arg, "%m", mg_print_esc, val.s.len, val.s.buf); + } else if (f->type == MG_VAL_FN) { + n += mg_xprintf(fn, arg, "%M", val.fn); } else { n += mg_xprintf(fn, arg, "null"); } return n; } -static inline bool mg_parse_field(struct mg_str json, struct mg_field *f) { +static inline bool mg_parse_field(struct mg_str json, struct mg_field *f, + union mg_val *val) { bool ok = false; if (f->type == MG_VAL_BOOL) { - ok = mg_json_get_bool(json, "$", &f->value.b); + ok = mg_json_get_bool(json, "$", &val->b); } else if (f->type == MG_VAL_INT) { double d; ok = mg_json_get_num(json, "$", &d); - if (ok) f->value.i = (int) d; + if (ok) val->i = (int) d; } else if (f->type == MG_VAL_DBL) { - ok = mg_json_get_num(json, "$", &f->value.d); + ok = mg_json_get_num(json, "$", &val->d); } else if (f->type == MG_VAL_STR) { - f->value.s = trimq(json); + val->s = trimq(json); + } else if (f->type == MG_VAL_FN) { + val->s = json; } return ok; } @@ -116,7 +115,7 @@ static inline bool mg_parse_field(struct mg_str json, struct mg_field *f) { static inline size_t mg_dash_print(mg_pfn_t fn, void *arg, va_list *ap) { struct mg_str *req = va_arg(*ap, struct mg_str *); struct mg_field *fields = va_arg(*ap, struct mg_field *); - mg_dash_get_fn get = va_arg(*ap, mg_dash_get_fn); + // mg_dash_get_fn get = va_arg(*ap, mg_dash_get_fn); struct mg_str name = trimq(mg_json_get_tok(*req, "$.params")); struct mg_field *f = mg_dash_find_field(fields, name); size_t i, n = 0; @@ -124,15 +123,12 @@ static inline size_t mg_dash_print(mg_pfn_t fn, void *arg, va_list *ap) { const char *comma = ""; n += mg_xprintf(fn, arg, "{"); for (i = 0; fields[i].name != NULL; i++) { - f = &fields[i]; - if (get) get(f); n += mg_xprintf(fn, arg, "%s", comma); - n += mg_xprintf(fn, arg, "%M", mg_print_field, f); + n += mg_xprintf(fn, arg, "%M", mg_print_field, &fields[i]); comma = ","; } n += mg_xprintf(fn, arg, "}"); } else if (f != NULL) { - if (get) get(f); n += mg_xprintf(fn, arg, "{%M}", mg_print_field, f); } else { n += mg_xprintf(fn, arg, "null"); @@ -140,58 +136,43 @@ static inline size_t mg_dash_print(mg_pfn_t fn, void *arg, va_list *ap) { return n; } -static inline bool mg_dash_sync(struct mg_mgr *mgr, struct mg_field *f, - mg_dash_get_fn get) { - union mg_val old_value = f->value; - bool changed = false; - if (get) get(f); - // Strings require special comparison - if (f->type == MG_VAL_STR && mg_strcmp(old_value.s, f->value.s) != 0) { - changed = true; - } else if (memcmp(&f->value, &old_value, sizeof(old_value)) != 0) { - changed = true; - } - if (changed && f != NULL) { +static inline void mg_dash_send_change(struct mg_mgr *mgr, struct mg_field *f) { + if (f != NULL) { mg_dash_broadcast(mgr, "{%m:%m,%m:{%M}}", MG_ESC("method"), MG_ESC("change"), MG_ESC("params"), mg_print_field, f); } - return changed; } -static inline bool mg_dash_apply(struct mg_connection *c, struct mg_str json, - struct mg_field *fields, mg_dash_get_fn get, - mg_dash_set_fn set) { +static inline void mg_dash_apply(struct mg_connection *c, struct mg_str json, + struct mg_field *fields) { struct mg_str key, val; size_t ofs = 0; struct mg_field *f = NULL; - bool changed = false; while ((ofs = mg_json_next(json, ofs, &key, &val)) > 0) { key = trimq(key); - if ((f = mg_dash_find_field(fields, key)) != NULL) { - struct mg_field tmp = *f; - mg_parse_field(val, &tmp); - if (set) set(&tmp); - if (mg_dash_sync(c->mgr, f, get)) changed = true; + if ((f = mg_dash_find_field(fields, key)) != NULL && f->set != NULL) { + union mg_val v = {0}; + mg_parse_field(val, f, &v); + f->set(&v); + mg_dash_send_change(c->mgr, f); break; } else { MG_ERROR(("UNKNOWN FIELD: [%.*s]", key.len, key.buf)); } } - return changed; } static inline void mg_dash_process_msg(struct mg_connection *c, struct mg_ws_message *wm, - struct mg_field *fields, - mg_dash_get_fn get, mg_dash_set_fn set) { + struct mg_field *fields) { struct mg_str req = wm->data; struct mg_str method = trimq(mg_json_get_tok(req, "$.method")); if (mg_match(method, mg_str("get"), NULL)) { - mg_dash_success(c, req, "%M", mg_dash_print, &req, fields, get); + mg_dash_success(c, req, "%M", mg_dash_print, &req, fields); } else if (mg_match(method, mg_str("set"), NULL)) { struct mg_str params = trimq(mg_json_get_tok(req, "$.params")); - bool changed = mg_dash_apply(c, params, fields, get, set); - mg_dash_success(c, req, "%s", changed ? "true" : "false"); + mg_dash_apply(c, params, fields); + mg_dash_success(c, req, "%s", "true"); } else { mg_dash_error(c, req, "%s", "unknown method"); } @@ -212,12 +193,12 @@ static inline void mg_dash_ev_handler(struct mg_connection *c, int ev, } } else if (ev == MG_EV_WS_MSG) { // Add this to automatically handle "get" and "set" JSON-RPC calls - struct mg_dash *dash = (struct mg_dash *) c->fn_data; + struct mg_field *fields = (struct mg_field *) c->fn_data; struct mg_ws_message *wm = (struct mg_ws_message *) ev_data; - if (dash == NULL || dash->fields == NULL) { + if (fields == NULL) { mg_dash_error(c, wm->data, "%s", "no fields defined"); } else { - mg_dash_process_msg(c, wm, dash->fields, dash->get, dash->set); + mg_dash_process_msg(c, wm, fields); } } }