+static void config_mix2_cb(void *closure, struct json_object *obj, const char *name)
+{
+ struct json_object *dest, *base = closure;
+
+ if (!name)
+ name = "";
+
+ if (!json_object_object_get_ex(base, name, &dest)) {
+ dest = joomchk(json_object_new_object());
+ json_object_object_add(base, name, dest);
+ }
+ if (json_object_is_type(obj, json_type_object))
+ wrap_json_object_add(dest, obj);
+ else
+ json_object_object_add(dest, "", json_object_get(obj));
+}
+
+static void config_mix2(struct json_object *config, int optid, struct json_object *val)
+{
+ struct json_object *obj;
+
+ if (!json_object_object_get_ex(config, name_of_optid(optid), &obj)) {
+ obj = joomchk(json_object_new_object());
+ json_object_object_add(config, name_of_optid(optid), obj);
+ }
+ wrap_json_for_all(val, config_mix2_cb, obj);
+}
+
+static void config_mix2_str(struct json_object *config, int optid, const char *val)
+{
+ size_t st1, st2;
+ const char *api, *key;
+ struct json_object *obj, *sub;
+ enum json_tokener_error jerr;
+
+ st1 = strcspn(val, "/:{[\"");
+ st2 = strcspn(&val[st1], ":{[\"");
+ if (val[st1] != '/' || val[st1 + st2] != ':') {
+ obj = json_tokener_parse_verbose(val, &jerr);
+ if (jerr != json_tokener_success)
+ obj = json_object_new_string(val);
+ } else {
+ api = st1 == 0 ? "*" : strndupa(val, st1);
+ val += st1 + 1;
+ key = st2 <= 1 || (st2 == 2 && *val == '*') ? NULL : strndupa(val, st2 - 1);
+ val += st2;
+ sub = json_tokener_parse_verbose(val, &jerr);
+ if (jerr != json_tokener_success)
+ sub = json_object_new_string(val);
+
+ if (key) {
+ obj = json_object_new_object();
+ json_object_object_add(obj, key, sub);
+ sub = obj;
+ }
+ obj = json_object_new_object();
+ json_object_object_add(obj, api, sub);
+ }
+ config_mix2(config, optid, obj);
+ json_object_put(obj);
+}
+
+static void config_mix2_optstr(struct json_object *config, int optid)
+{
+ config_mix2_str(config, optid, get_arg(optid));
+}
+