static GenericList *qmp_input_next_list(Visitor *v, GenericList **list, Error **errp) { QmpInputVisitor *qiv = to_qiv(v); GenericList *entry; StackObject *so = &qiv->stack[qiv->nb_stack - 1]; bool first; if (so->entry == NULL) { so->entry = qlist_first(qobject_to_qlist(so->obj)); first = true; } else { so->entry = qlist_next(so->entry); first = false; } if (so->entry == NULL) { return NULL; } entry = g_malloc0(sizeof(*entry)); if (first) { *list = entry; } else { (*list)->next = entry; } return entry; }
static void qobject_to_qlist_test(void) { QList *qlist; qlist = qlist_new(); g_assert(qobject_to_qlist(QOBJECT(qlist)) == qlist); // destroy doesn't exist yet g_free(qlist); }
static void qmp_input_push(QmpInputVisitor *qiv, const QObject *obj, Error **errp) { qiv->stack[qiv->nb_stack].obj = obj; if (qobject_type(obj) == QTYPE_QLIST) { qiv->stack[qiv->nb_stack].entry = qlist_first(qobject_to_qlist(obj)); } qiv->nb_stack++; if (qiv->nb_stack >= QIV_STACK_SIZE) { error_set(errp, QERR_BUFFER_OVERRUN); return; } }
static int qemu_rbd_set_keypairs(rados_t cluster, const char *keypairs_json, Error **errp) { QList *keypairs; QString *name; QString *value; const char *key; size_t remaining; int ret = 0; if (!keypairs_json) { return ret; } keypairs = qobject_to_qlist(qobject_from_json(keypairs_json, &error_abort)); remaining = qlist_size(keypairs) / 2; assert(remaining); while (remaining--) { name = qobject_to_qstring(qlist_pop(keypairs)); value = qobject_to_qstring(qlist_pop(keypairs)); assert(name && value); key = qstring_get_str(name); ret = rados_conf_set(cluster, key, qstring_get_str(value)); QDECREF(name); QDECREF(value); if (ret < 0) { error_setg_errno(errp, -ret, "invalid conf option %s", key); ret = -EINVAL; break; } } QDECREF(keypairs); return ret; }
static void to_json(const QObject *obj, QString *str) { switch (qobject_type(obj)) { case QTYPE_QINT: { QInt *val = qobject_to_qint(obj); char buffer[1024]; snprintf(buffer, sizeof(buffer), "%" PRId64, qint_get_int(val)); qstring_append(str, buffer); break; } case QTYPE_QSTRING: { QString *val = qobject_to_qstring(obj); const char *ptr; ptr = qstring_get_str(val); qstring_append(str, "\""); while (*ptr) { if ((ptr[0] & 0xE0) == 0xE0 && (ptr[1] & 0x80) && (ptr[2] & 0x80)) { uint16_t wchar; char escape[7]; wchar = (ptr[0] & 0x0F) << 12; wchar |= (ptr[1] & 0x3F) << 6; wchar |= (ptr[2] & 0x3F); ptr += 2; snprintf(escape, sizeof(escape), "\\u%04X", wchar); qstring_append(str, escape); } else if ((ptr[0] & 0xE0) == 0xC0 && (ptr[1] & 0x80)) { uint16_t wchar; char escape[7]; wchar = (ptr[0] & 0x1F) << 6; wchar |= (ptr[1] & 0x3F); ptr++; snprintf(escape, sizeof(escape), "\\u%04X", wchar); qstring_append(str, escape); } else switch (ptr[0]) { case '\"': qstring_append(str, "\\\""); break; case '\\': qstring_append(str, "\\\\"); break; case '\b': qstring_append(str, "\\b"); break; case '\f': qstring_append(str, "\\f"); break; case '\n': qstring_append(str, "\\n"); break; case '\r': qstring_append(str, "\\r"); break; case '\t': qstring_append(str, "\\t"); break; default: { if (ptr[0] <= 0x1F) { char escape[7]; snprintf(escape, sizeof(escape), "\\u%04X", ptr[0]); qstring_append(str, escape); } else { char buf[2] = { ptr[0], 0 }; qstring_append(str, buf); } break; } } ptr++; } qstring_append(str, "\""); break; } case QTYPE_QDICT: { ToJsonIterState s; QDict *val = qobject_to_qdict(obj); s.count = 0; s.str = str; qstring_append(str, "{"); qdict_iter(val, to_json_dict_iter, &s); qstring_append(str, "}"); break; } case QTYPE_QLIST: { ToJsonIterState s; QList *val = qobject_to_qlist(obj); s.count = 0; s.str = str; qstring_append(str, "["); qlist_iter(val, (void *)to_json_list_iter, &s); qstring_append(str, "]"); break; } case QTYPE_QFLOAT: { QFloat *val = qobject_to_qfloat(obj); char buffer[1024]; int len; len = snprintf(buffer, sizeof(buffer), "%f", qfloat_get_double(val)); while (len > 0 && buffer[len - 1] == '0') { len--; } if (len && buffer[len - 1] == '.') { buffer[len - 1] = 0; } else { buffer[len] = 0; } qstring_append(str, buffer); break; } case QTYPE_QBOOL: { QBool *val = qobject_to_qbool(obj); if (qbool_get_int(val)) { qstring_append(str, "true"); } else { qstring_append(str, "false"); } break; } case QTYPE_QERROR: /* XXX: should QError be emitted? */ case QTYPE_NONE: break; } }
/* test core visitor methods */ static void test_visitor_core(void) { QmpOutputVisitor *mo; QmpInputVisitor *mi; Visitor *v; TestStruct ts = { 42, 82 }; TestStruct *pts = &ts; TestStructList *lts = NULL; Error *err = NULL; QObject *obj; QList *qlist; QDict *qdict; QString *str; int64_t value = 0; mo = qmp_output_visitor_new(); v = qmp_output_get_visitor(mo); visit_type_TestStruct(v, &pts, NULL, &err); obj = qmp_output_get_qobject(mo); str = qobject_to_json(obj); printf("%s\n", qstring_get_str(str)); QDECREF(str); obj = QOBJECT(qint_from_int(0x42)); mi = qmp_input_visitor_new(obj); v = qmp_input_get_visitor(mi); visit_type_int(v, &value, NULL, &err); if (err) { g_error("%s", error_get_pretty(err)); } g_assert(value == 0x42); qobject_decref(obj); obj = qobject_from_json("{'x': 42, 'y': 84}"); mi = qmp_input_visitor_new(obj); v = qmp_input_get_visitor(mi); pts = NULL; visit_type_TestStruct(v, &pts, NULL, &err); if (err) { g_error("%s", error_get_pretty(err)); } g_assert(pts != NULL); g_assert(pts->x == 42); g_assert(pts->y == 84); qobject_decref(obj); g_free(pts); /* test list input visitor */ obj = qobject_from_json("[{'x': 42, 'y': 84}, {'x': 12, 'y': 24}]"); mi = qmp_input_visitor_new(obj); v = qmp_input_get_visitor(mi); visit_type_TestStructList(v, <s, NULL, &err); if (err) { g_error("%s", error_get_pretty(err)); } g_assert(lts != NULL); g_assert(lts->value->x == 42); g_assert(lts->value->y == 84); g_assert(lts->next != NULL); g_assert(lts->next->value->x == 12); g_assert(lts->next->value->y == 24); g_assert(lts->next->next == NULL); qobject_decref(obj); /* test list output visitor */ mo = qmp_output_visitor_new(); v = qmp_output_get_visitor(mo); visit_type_TestStructList(v, <s, NULL, &err); if (err) { g_error("%s", error_get_pretty(err)); } obj = qmp_output_get_qobject(mo); g_print("obj: %s\n", qstring_get_str(qobject_to_json(obj))); qlist = qobject_to_qlist(obj); assert(qlist); obj = qlist_pop(qlist); qdict = qobject_to_qdict(obj); assert(qdict); assert(qdict_get_int(qdict, "x") == 42); assert(qdict_get_int(qdict, "y") == 84); qobject_decref(obj); obj = qlist_pop(qlist); qdict = qobject_to_qdict(obj); assert(qdict); assert(qdict_get_int(qdict, "x") == 12); assert(qdict_get_int(qdict, "y") == 24); qobject_decref(obj); qmp_output_visitor_cleanup(mo); QDECREF(qlist); }
QList *qdict_get_qlist(const QDict *qdict, const char *key) { return qobject_to_qlist(qdict_get_obj(qdict, key, QTYPE_QLIST)); }
static void qdict_crumple_test_recursive(void) { QDict *src, *dst, *rule, *vnc, *acl, *listen; QObject *child, *res; QList *rules; src = qdict_new(); qdict_put(src, "vnc.listen.addr", qstring_from_str("127.0.0.1")); qdict_put(src, "vnc.listen.port", qstring_from_str("5901")); qdict_put(src, "vnc.acl.rules.0.match", qstring_from_str("fred")); qdict_put(src, "vnc.acl.rules.0.policy", qstring_from_str("allow")); qdict_put(src, "vnc.acl.rules.1.match", qstring_from_str("bob")); qdict_put(src, "vnc.acl.rules.1.policy", qstring_from_str("deny")); qdict_put(src, "vnc.acl.default", qstring_from_str("deny")); qdict_put(src, "vnc.acl..name", qstring_from_str("acl0")); qdict_put(src, "vnc.acl.rule..name", qstring_from_str("acl0")); res = qdict_crumple(src, &error_abort); g_assert_cmpint(qobject_type(res), ==, QTYPE_QDICT); dst = qobject_to_qdict(res); g_assert_cmpint(qdict_size(dst), ==, 1); child = qdict_get(dst, "vnc"); g_assert_cmpint(qobject_type(child), ==, QTYPE_QDICT); vnc = qobject_to_qdict(child); child = qdict_get(vnc, "listen"); g_assert_cmpint(qobject_type(child), ==, QTYPE_QDICT); listen = qobject_to_qdict(child); g_assert_cmpstr("127.0.0.1", ==, qdict_get_str(listen, "addr")); g_assert_cmpstr("5901", ==, qdict_get_str(listen, "port")); child = qdict_get(vnc, "acl"); g_assert_cmpint(qobject_type(child), ==, QTYPE_QDICT); acl = qobject_to_qdict(child); child = qdict_get(acl, "rules"); g_assert_cmpint(qobject_type(child), ==, QTYPE_QLIST); rules = qobject_to_qlist(child); g_assert_cmpint(qlist_size(rules), ==, 2); rule = qobject_to_qdict(qlist_pop(rules)); g_assert_cmpint(qdict_size(rule), ==, 2); g_assert_cmpstr("fred", ==, qdict_get_str(rule, "match")); g_assert_cmpstr("allow", ==, qdict_get_str(rule, "policy")); QDECREF(rule); rule = qobject_to_qdict(qlist_pop(rules)); g_assert_cmpint(qdict_size(rule), ==, 2); g_assert_cmpstr("bob", ==, qdict_get_str(rule, "match")); g_assert_cmpstr("deny", ==, qdict_get_str(rule, "policy")); QDECREF(rule); /* With recursive crumpling, we should see all names unescaped */ g_assert_cmpstr("acl0", ==, qdict_get_str(vnc, "acl.name")); child = qdict_get(vnc, "acl"); g_assert_cmpint(qobject_type(child), ==, QTYPE_QDICT); acl = qdict_get_qdict(vnc, "acl"); g_assert_cmpstr("acl0", ==, qdict_get_str(acl, "rule.name")); QDECREF(src); QDECREF(dst); }