QAPI patches patches for 2020-12-19

-----BEGIN PGP SIGNATURE-----
 
 iQJGBAABCAAwFiEENUvIs9frKmtoZ05fOHC0AOuRhlMFAl/dynUSHGFybWJydUBy
 ZWRoYXQuY29tAAoJEDhwtADrkYZT3igP/3bWwsKR5vKVsDUTmMfrhcgaFvQiaYoG
 F29Bond8Xy0Zd0gl7OWh/5jKL0vGlrEVPrKfYLUjMnfkeRec/pOkIB2oOmIxpnPs
 9zi4kh2hQ3dEoRBuvSnnZzedetYPTuCpWMIjlztkgfxgcimqm8TPNVSxRaSApjC3
 Y8108wGwBWVf2C0rhKO9E2xA51uo6khy05i1psUtqUlC+PuDQ/OwzQHM2dnWdDB6
 kUwBDK17nhL6WwsYqCyKLSiDModReYfDiY8GS5MDLo74dzwXiatEefCR7+sbM4xq
 eX/SBoqoeS1jLPNuCryNeGNKvNA2KAbEJTnbQA2NxBXHgZ9/1SxVZFxuPp4nDMSQ
 N7BDuDI8YtJE479RjT/ZzRG65xadGBSe/HXkXM9mZwh1zitop8SVZ9fArFBHvNzw
 Y5zAv3fQd54+87psffg4dYFK0wGmqTabLEEuVzM8KIVqcAdYA2yC2b2EHy+vsxuq
 GMkr0WaA6Sq2gthXmzdTjmUPuHdan/NIhuV6d66SbPNH2oH31piptFxuznyFWSKV
 isciFFdUrkg5QrF8DSt2nmdwMFf8QGbszqP8QIGMzhJCCS9GXIiGG8f149++q8X8
 HO1lFAdLQJdrDwCYmfx36tOvi2rS/rcoTGgvg66UX3xKko1ruoxR1ZWcS54obJN6
 vEQDZ+PxubDg
 =vGLy
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/armbru/tags/pull-qapi-2020-12-19' into staging

QAPI patches patches for 2020-12-19

# gpg: Signature made Sat 19 Dec 2020 09:40:05 GMT
# gpg:                using RSA key 354BC8B3D7EB2A6B68674E5F3870B400EB918653
# gpg:                issuer "armbru@redhat.com"
# gpg: Good signature from "Markus Armbruster <armbru@redhat.com>" [full]
# gpg:                 aka "Markus Armbruster <armbru@pond.sub.org>" [full]
# Primary key fingerprint: 354B C8B3 D7EB 2A6B 6867  4E5F 3870 B400 EB91 8653

* remotes/armbru/tags/pull-qapi-2020-12-19: (33 commits)
  qobject: Make QString immutable
  block: Use GString instead of QString to build filenames
  keyval: Use GString to accumulate value strings
  json: Use GString instead of QString to accumulate strings
  migration: Replace migration's JSON writer by the general one
  qobject: Factor JSON writer out of qobject_to_json()
  qobject: Factor quoted_str() out of to_json()
  qobject: Drop qstring_get_try_str()
  qobject: Drop qobject_get_try_str()
  Revert "qobject: let object_property_get_str() use new API"
  block: Avoid qobject_get_try_str()
  qmp: Fix tracing of non-string command IDs
  qobject: Move internals to qobject-internal.h
  hw/rdma: Replace QList by GQueue
  Revert "qstring: add qstring_free()"
  qobject: Change qobject_to_json()'s value to GString
  qobject: Use GString instead of QString to accumulate JSON
  qobject: Make qobject_to_json_pretty() take a pretty argument
  monitor: Use GString instead of QString for output buffer
  hmp: Simplify how qmp_human_monitor_command() gets output
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2021-01-01 14:33:03 +00:00
commit 1f7c02797f
105 changed files with 975 additions and 1263 deletions

23
block.c
View File

@ -217,7 +217,7 @@ void bdrv_parse_filename_strip_prefix(const char *filename, const char *prefix,
/* Stripping the explicit protocol prefix may result in a protocol /* Stripping the explicit protocol prefix may result in a protocol
* prefix being (wrongly) detected (if the filename contains a colon) */ * prefix being (wrongly) detected (if the filename contains a colon) */
if (path_has_protocol(filename)) { if (path_has_protocol(filename)) {
QString *fat_filename; GString *fat_filename;
/* This means there is some colon before the first slash; therefore, /* This means there is some colon before the first slash; therefore,
* this cannot be an absolute path */ * this cannot be an absolute path */
@ -225,12 +225,13 @@ void bdrv_parse_filename_strip_prefix(const char *filename, const char *prefix,
/* And we can thus fix the protocol detection issue by prefixing it /* And we can thus fix the protocol detection issue by prefixing it
* by "./" */ * by "./" */
fat_filename = qstring_from_str("./"); fat_filename = g_string_new("./");
qstring_append(fat_filename, filename); g_string_append(fat_filename, filename);
assert(!path_has_protocol(qstring_get_str(fat_filename))); assert(!path_has_protocol(fat_filename->str));
qdict_put(options, "filename", fat_filename); qdict_put(options, "filename",
qstring_from_gstring(fat_filename));
} else { } else {
/* If no protocol prefix was detected, we can use the shortened /* If no protocol prefix was detected, we can use the shortened
* filename as-is */ * filename as-is */
@ -3977,7 +3978,7 @@ static int bdrv_reopen_parse_backing(BDRVReopenState *reopen_state,
new_backing_bs = NULL; new_backing_bs = NULL;
break; break;
case QTYPE_QSTRING: case QTYPE_QSTRING:
str = qobject_get_try_str(value); str = qstring_get_str(qobject_to(QString, value));
new_backing_bs = bdrv_lookup_bs(NULL, str, errp); new_backing_bs = bdrv_lookup_bs(NULL, str, errp);
if (new_backing_bs == NULL) { if (new_backing_bs == NULL) {
return -EINVAL; return -EINVAL;
@ -4240,8 +4241,8 @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
} }
if (child) { if (child) {
const char *str = qobject_get_try_str(new); if (!strcmp(child->bs->node_name,
if (!strcmp(child->bs->node_name, str)) { qstring_get_str(qobject_to(QString, new)))) {
continue; /* Found child with this name, skip option */ continue; /* Found child with this name, skip option */
} }
} }
@ -6938,13 +6939,13 @@ void bdrv_refresh_filename(BlockDriverState *bs)
if (bs->exact_filename[0]) { if (bs->exact_filename[0]) {
pstrcpy(bs->filename, sizeof(bs->filename), bs->exact_filename); pstrcpy(bs->filename, sizeof(bs->filename), bs->exact_filename);
} else { } else {
QString *json = qobject_to_json(QOBJECT(bs->full_open_options)); GString *json = qobject_to_json(QOBJECT(bs->full_open_options));
if (snprintf(bs->filename, sizeof(bs->filename), "json:%s", if (snprintf(bs->filename, sizeof(bs->filename), "json:%s",
qstring_get_str(json)) >= sizeof(bs->filename)) { json->str) >= sizeof(bs->filename)) {
/* Give user a hint if we truncated things. */ /* Give user a hint if we truncated things. */
strcpy(bs->filename + sizeof(bs->filename) - 4, "..."); strcpy(bs->filename + sizeof(bs->filename) - 4, "...");
} }
qobject_unref(json); g_string_free(json, true);
} }
} }

View File

@ -359,8 +359,8 @@ static int qemu_gluster_parse_uri(BlockdevOptionsGluster *gconf,
return -EINVAL; return -EINVAL;
} }
gconf->server = g_new0(SocketAddressList, 1); gsconf = g_new0(SocketAddress, 1);
gconf->server->value = gsconf = g_new0(SocketAddress, 1); QAPI_LIST_PREPEND(gconf->server, gsconf);
/* transport */ /* transport */
if (!uri->scheme || !strcmp(uri->scheme, "gluster")) { if (!uri->scheme || !strcmp(uri->scheme, "gluster")) {

View File

@ -486,12 +486,7 @@ static void bdrv_query_blk_stats(BlockDeviceStats *ds, BlockBackend *blk)
ds->account_failed = stats->account_failed; ds->account_failed = stats->account_failed;
while ((ts = block_acct_interval_next(stats, ts))) { while ((ts = block_acct_interval_next(stats, ts))) {
BlockDeviceTimedStatsList *timed_stats =
g_malloc0(sizeof(*timed_stats));
BlockDeviceTimedStats *dev_stats = g_malloc0(sizeof(*dev_stats)); BlockDeviceTimedStats *dev_stats = g_malloc0(sizeof(*dev_stats));
timed_stats->next = ds->timed_stats;
timed_stats->value = dev_stats;
ds->timed_stats = timed_stats;
TimedAverage *rd = &ts->latency[BLOCK_ACCT_READ]; TimedAverage *rd = &ts->latency[BLOCK_ACCT_READ];
TimedAverage *wr = &ts->latency[BLOCK_ACCT_WRITE]; TimedAverage *wr = &ts->latency[BLOCK_ACCT_WRITE];
@ -515,6 +510,8 @@ static void bdrv_query_blk_stats(BlockDeviceStats *ds, BlockBackend *blk)
block_acct_queue_depth(ts, BLOCK_ACCT_READ); block_acct_queue_depth(ts, BLOCK_ACCT_READ);
dev_stats->avg_wr_queue_depth = dev_stats->avg_wr_queue_depth =
block_acct_queue_depth(ts, BLOCK_ACCT_WRITE); block_acct_queue_depth(ts, BLOCK_ACCT_WRITE);
QAPI_LIST_PREPEND(ds->timed_stats, dev_stats);
} }
bdrv_latency_histogram_stats(&stats->latency_histogram[BLOCK_ACCT_READ], bdrv_latency_histogram_stats(&stats->latency_histogram[BLOCK_ACCT_READ],

View File

@ -232,7 +232,7 @@ static void qemu_rbd_parse_filename(const char *filename, QDict *options,
if (keypairs) { if (keypairs) {
qdict_put(options, "=keyvalue-pairs", qdict_put(options, "=keyvalue-pairs",
qobject_to_json(QOBJECT(keypairs))); qstring_from_gstring(qobject_to_json(QOBJECT(keypairs))));
} }
done: done:

View File

@ -776,15 +776,13 @@ static int qmp_query_chardev_foreach(Object *obj, void *data)
{ {
Chardev *chr = CHARDEV(obj); Chardev *chr = CHARDEV(obj);
ChardevInfoList **list = data; ChardevInfoList **list = data;
ChardevInfoList *info = g_malloc0(sizeof(*info)); ChardevInfo *value = g_malloc0(sizeof(*value));
info->value = g_malloc0(sizeof(*info->value)); value->label = g_strdup(chr->label);
info->value->label = g_strdup(chr->label); value->filename = g_strdup(chr->filename);
info->value->filename = g_strdup(chr->filename); value->frontend_open = chr->be && chr->be->fe_open;
info->value->frontend_open = chr->be && chr->be->fe_open;
info->next = *list; QAPI_LIST_PREPEND(*list, value);
*list = info;
return 0; return 0;
} }
@ -803,12 +801,10 @@ static void
qmp_prepend_backend(const char *name, void *opaque) qmp_prepend_backend(const char *name, void *opaque)
{ {
ChardevBackendInfoList **list = opaque; ChardevBackendInfoList **list = opaque;
ChardevBackendInfoList *info = g_malloc0(sizeof(*info)); ChardevBackendInfo *value = g_new0(ChardevBackendInfo, 1);
info->value = g_malloc0(sizeof(*info->value)); value->name = g_strdup(name);
info->value->name = g_strdup(name); QAPI_LIST_PREPEND(*list, value);
info->next = *list;
*list = info;
} }
ChardevBackendInfoList *qmp_query_chardev_backends(Error **errp) ChardevBackendInfoList *qmp_query_chardev_backends(Error **errp)

View File

@ -531,15 +531,11 @@ TimerAlarmMethodList *qmp_query_alarm_methods(Error **errp)
bool current = true; bool current = true;
for (p = alarm_timers; p->name; p++) { for (p = alarm_timers; p->name; p++) {
TimerAlarmMethodList *info = g_malloc0(sizeof(*info)); TimerAlarmMethod *value = g_malloc0(*value);
info->value = g_malloc0(sizeof(*info->value)); value->method_name = g_strdup(p->name);
info->value->method_name = g_strdup(p->name); value->current = current;
info->value->current = current; QAPI_LIST_PREPEND(method_list, value);
current = false; current = false;
info->next = method_list;
method_list = info;
} }
return method_list; return method_list;

View File

@ -215,7 +215,6 @@ MachineInfoList *qmp_query_machines(Error **errp)
for (el = machines; el; el = el->next) { for (el = machines; el; el = el->next) {
MachineClass *mc = el->data; MachineClass *mc = el->data;
MachineInfoList *entry;
MachineInfo *info; MachineInfo *info;
info = g_malloc0(sizeof(*info)); info = g_malloc0(sizeof(*info));
@ -243,10 +242,7 @@ MachineInfoList *qmp_query_machines(Error **errp)
info->has_default_ram_id = true; info->has_default_ram_id = true;
} }
entry = g_malloc0(sizeof(*entry)); QAPI_LIST_PREPEND(mach_list, info);
entry->value = info;
entry->next = mach_list;
mach_list = entry;
} }
g_slist_free(machines); g_slist_free(machines);

View File

@ -504,11 +504,7 @@ static void machine_set_nvdimm_persistence(Object *obj, const char *value,
void machine_class_allow_dynamic_sysbus_dev(MachineClass *mc, const char *type) void machine_class_allow_dynamic_sysbus_dev(MachineClass *mc, const char *type)
{ {
strList *item = g_new0(strList, 1); QAPI_LIST_PREPEND(mc->allowed_dynamic_sysbus_devices, g_strdup(type));
item->value = g_strdup(type);
item->next = mc->allowed_dynamic_sysbus_devices;
mc->allowed_dynamic_sysbus_devices = item;
} }
static void validate_sysbus_device(SysBusDevice *sbdev, void *opaque) static void validate_sysbus_device(SysBusDevice *sbdev, void *opaque)
@ -569,7 +565,6 @@ HotpluggableCPUList *machine_query_hotpluggable_cpus(MachineState *machine)
for (i = 0; i < machine->possible_cpus->len; i++) { for (i = 0; i < machine->possible_cpus->len; i++) {
Object *cpu; Object *cpu;
HotpluggableCPUList *list_item = g_new0(typeof(*list_item), 1);
HotpluggableCPU *cpu_item = g_new0(typeof(*cpu_item), 1); HotpluggableCPU *cpu_item = g_new0(typeof(*cpu_item), 1);
cpu_item->type = g_strdup(machine->possible_cpus->cpus[i].type); cpu_item->type = g_strdup(machine->possible_cpus->cpus[i].type);
@ -582,9 +577,7 @@ HotpluggableCPUList *machine_query_hotpluggable_cpus(MachineState *machine)
cpu_item->has_qom_path = true; cpu_item->has_qom_path = true;
cpu_item->qom_path = object_get_canonical_path(cpu); cpu_item->qom_path = object_get_canonical_path(cpu);
} }
list_item->value = cpu_item; QAPI_LIST_PREPEND(head, cpu_item);
list_item->next = head;
head = list_item;
} }
return head; return head;
} }

View File

@ -970,7 +970,7 @@ static const VMStateDescription vmstate_virtio_gpu_scanouts = {
}; };
static int virtio_gpu_save(QEMUFile *f, void *opaque, size_t size, static int virtio_gpu_save(QEMUFile *f, void *opaque, size_t size,
const VMStateField *field, QJSON *vmdesc) const VMStateField *field, JSONWriter *vmdesc)
{ {
VirtIOGPU *g = opaque; VirtIOGPU *g = opaque;
struct virtio_gpu_simple_resource *res; struct virtio_gpu_simple_resource *res;

View File

@ -386,7 +386,7 @@ static void kvm_s390_release_adapter_routes(S390FLICState *fs,
* reached * reached
*/ */
static int kvm_flic_save(QEMUFile *f, void *opaque, size_t size, static int kvm_flic_save(QEMUFile *f, void *opaque, size_t size,
const VMStateField *field, QJSON *vmdesc) const VMStateField *field, JSONWriter *vmdesc)
{ {
KVMS390FLICState *flic = opaque; KVMS390FLICState *flic = opaque;
int len = FLIC_SAVE_INITIAL_SIZE; int len = FLIC_SAVE_INITIAL_SIZE;

View File

@ -127,13 +127,7 @@ RockerPortList *qmp_query_rocker_ports(const char *name, Error **errp)
} }
for (i = r->fp_ports - 1; i >= 0; i--) { for (i = r->fp_ports - 1; i >= 0; i--) {
RockerPortList *info = g_malloc0(sizeof(*info)); QAPI_LIST_PREPEND(list, fp_port_get_info(r->fp_port[i]));
info->value = g_malloc0(sizeof(*info->value));
struct fp_port *port = r->fp_port[i];
fp_port_get_info(port, info);
info->next = list;
list = info;
} }
return list; return list;

View File

@ -51,14 +51,17 @@ bool fp_port_get_link_up(FpPort *port)
return !qemu_get_queue(port->nic)->link_down; return !qemu_get_queue(port->nic)->link_down;
} }
void fp_port_get_info(FpPort *port, RockerPortList *info) RockerPort *fp_port_get_info(FpPort *port)
{ {
info->value->name = g_strdup(port->name); RockerPort *value = g_malloc0(sizeof(*value));
info->value->enabled = port->enabled;
info->value->link_up = fp_port_get_link_up(port); value->name = g_strdup(port->name);
info->value->speed = port->speed; value->enabled = port->enabled;
info->value->duplex = port->duplex; value->link_up = fp_port_get_link_up(port);
info->value->autoneg = port->autoneg; value->speed = port->speed;
value->duplex = port->duplex;
value->autoneg = port->autoneg;
return value;
} }
void fp_port_get_macaddr(FpPort *port, MACAddr *macaddr) void fp_port_get_macaddr(FpPort *port, MACAddr *macaddr)

View File

@ -28,7 +28,7 @@ int fp_port_eg(FpPort *port, const struct iovec *iov, int iovcnt);
char *fp_port_get_name(FpPort *port); char *fp_port_get_name(FpPort *port);
bool fp_port_get_link_up(FpPort *port); bool fp_port_get_link_up(FpPort *port);
void fp_port_get_info(FpPort *port, RockerPortList *info); RockerPort *fp_port_get_info(FpPort *port);
void fp_port_get_macaddr(FpPort *port, MACAddr *macaddr); void fp_port_get_macaddr(FpPort *port, MACAddr *macaddr);
void fp_port_set_macaddr(FpPort *port, MACAddr *macaddr); void fp_port_set_macaddr(FpPort *port, MACAddr *macaddr);
uint8_t fp_port_get_learning(FpPort *port); uint8_t fp_port_get_learning(FpPort *port);

View File

@ -2296,7 +2296,6 @@ static void of_dpa_flow_fill(void *cookie, void *value, void *user_data)
struct of_dpa_flow_key *key = &flow->key; struct of_dpa_flow_key *key = &flow->key;
struct of_dpa_flow_key *mask = &flow->mask; struct of_dpa_flow_key *mask = &flow->mask;
struct of_dpa_flow_fill_context *flow_context = user_data; struct of_dpa_flow_fill_context *flow_context = user_data;
RockerOfDpaFlowList *new;
RockerOfDpaFlow *nflow; RockerOfDpaFlow *nflow;
RockerOfDpaFlowKey *nkey; RockerOfDpaFlowKey *nkey;
RockerOfDpaFlowMask *nmask; RockerOfDpaFlowMask *nmask;
@ -2307,8 +2306,7 @@ static void of_dpa_flow_fill(void *cookie, void *value, void *user_data)
return; return;
} }
new = g_malloc0(sizeof(*new)); nflow = g_malloc0(sizeof(*nflow));
nflow = new->value = g_malloc0(sizeof(*nflow));
nkey = nflow->key = g_malloc0(sizeof(*nkey)); nkey = nflow->key = g_malloc0(sizeof(*nkey));
nmask = nflow->mask = g_malloc0(sizeof(*nmask)); nmask = nflow->mask = g_malloc0(sizeof(*nmask));
naction = nflow->action = g_malloc0(sizeof(*naction)); naction = nflow->action = g_malloc0(sizeof(*naction));
@ -2424,8 +2422,7 @@ static void of_dpa_flow_fill(void *cookie, void *value, void *user_data)
naction->new_vlan_id = flow->action.apply.new_vlan_id; naction->new_vlan_id = flow->action.apply.new_vlan_id;
} }
new->next = flow_context->list; QAPI_LIST_PREPEND(flow_context->list, nflow);
flow_context->list = new;
} }
RockerOfDpaFlowList *qmp_query_rocker_of_dpa_flows(const char *name, RockerOfDpaFlowList *qmp_query_rocker_of_dpa_flows(const char *name,
@ -2469,9 +2466,7 @@ static void of_dpa_group_fill(void *key, void *value, void *user_data)
{ {
struct of_dpa_group *group = value; struct of_dpa_group *group = value;
struct of_dpa_group_fill_context *flow_context = user_data; struct of_dpa_group_fill_context *flow_context = user_data;
RockerOfDpaGroupList *new;
RockerOfDpaGroup *ngroup; RockerOfDpaGroup *ngroup;
struct uint32List *id;
int i; int i;
if (flow_context->type != 9 && if (flow_context->type != 9 &&
@ -2479,8 +2474,7 @@ static void of_dpa_group_fill(void *key, void *value, void *user_data)
return; return;
} }
new = g_malloc0(sizeof(*new)); ngroup = g_malloc0(sizeof(*ngroup));
ngroup = new->value = g_malloc0(sizeof(*ngroup));
ngroup->id = group->id; ngroup->id = group->id;
@ -2525,10 +2519,7 @@ static void of_dpa_group_fill(void *key, void *value, void *user_data)
ngroup->index = ROCKER_GROUP_INDEX_GET(group->id); ngroup->index = ROCKER_GROUP_INDEX_GET(group->id);
for (i = 0; i < group->l2_flood.group_count; i++) { for (i = 0; i < group->l2_flood.group_count; i++) {
ngroup->has_group_ids = true; ngroup->has_group_ids = true;
id = g_malloc0(sizeof(*id)); QAPI_LIST_PREPEND(ngroup->group_ids, group->l2_flood.group_ids[i]);
id->value = group->l2_flood.group_ids[i];
id->next = ngroup->group_ids;
ngroup->group_ids = id;
} }
break; break;
case ROCKER_OF_DPA_GROUP_TYPE_L3_UCAST: case ROCKER_OF_DPA_GROUP_TYPE_L3_UCAST:
@ -2557,8 +2548,7 @@ static void of_dpa_group_fill(void *key, void *value, void *user_data)
break; break;
} }
new->next = flow_context->list; QAPI_LIST_PREPEND(flow_context->list, ngroup);
flow_context->list = new;
} }
RockerOfDpaGroupList *qmp_query_rocker_of_dpa_groups(const char *name, RockerOfDpaGroupList *qmp_query_rocker_of_dpa_groups(const char *name,

View File

@ -437,17 +437,14 @@ static void rxfilter_notify(NetClientState *nc)
static intList *get_vlan_table(VirtIONet *n) static intList *get_vlan_table(VirtIONet *n)
{ {
intList *list, *entry; intList *list;
int i, j; int i, j;
list = NULL; list = NULL;
for (i = 0; i < MAX_VLAN >> 5; i++) { for (i = 0; i < MAX_VLAN >> 5; i++) {
for (j = 0; n->vlans[i] && j <= 0x1f; j++) { for (j = 0; n->vlans[i] && j <= 0x1f; j++) {
if (n->vlans[i] & (1U << j)) { if (n->vlans[i] & (1U << j)) {
entry = g_malloc0(sizeof(*entry)); QAPI_LIST_PREPEND(list, (i << 5) + j);
entry->value = (i << 5) + j;
entry->next = list;
list = entry;
} }
} }
} }
@ -460,7 +457,7 @@ static RxFilterInfo *virtio_net_query_rxfilter(NetClientState *nc)
VirtIONet *n = qemu_get_nic_opaque(nc); VirtIONet *n = qemu_get_nic_opaque(nc);
VirtIODevice *vdev = VIRTIO_DEVICE(n); VirtIODevice *vdev = VIRTIO_DEVICE(n);
RxFilterInfo *info; RxFilterInfo *info;
strList *str_list, *entry; strList *str_list;
int i; int i;
info = g_malloc0(sizeof(*info)); info = g_malloc0(sizeof(*info));
@ -491,19 +488,15 @@ static RxFilterInfo *virtio_net_query_rxfilter(NetClientState *nc)
str_list = NULL; str_list = NULL;
for (i = 0; i < n->mac_table.first_multi; i++) { for (i = 0; i < n->mac_table.first_multi; i++) {
entry = g_malloc0(sizeof(*entry)); QAPI_LIST_PREPEND(str_list,
entry->value = qemu_mac_strdup_printf(n->mac_table.macs + i * ETH_ALEN); qemu_mac_strdup_printf(n->mac_table.macs + i * ETH_ALEN));
entry->next = str_list;
str_list = entry;
} }
info->unicast_table = str_list; info->unicast_table = str_list;
str_list = NULL; str_list = NULL;
for (i = n->mac_table.first_multi; i < n->mac_table.in_use; i++) { for (i = n->mac_table.first_multi; i < n->mac_table.in_use; i++) {
entry = g_malloc0(sizeof(*entry)); QAPI_LIST_PREPEND(str_list,
entry->value = qemu_mac_strdup_printf(n->mac_table.macs + i * ETH_ALEN); qemu_mac_strdup_printf(n->mac_table.macs + i * ETH_ALEN));
entry->next = str_list;
str_list = entry;
} }
info->multicast_table = str_list; info->multicast_table = str_list;
info->vlan_table = get_vlan_table(n); info->vlan_table = get_vlan_table(n);

View File

@ -104,7 +104,7 @@ static int get_uint16_from_uint8(QEMUFile *f, void *pv, size_t size,
} }
static int put_unused(QEMUFile *f, void *pv, size_t size, static int put_unused(QEMUFile *f, void *pv, size_t size,
const VMStateField *field, QJSON *vmdesc) const VMStateField *field, JSONWriter *vmdesc)
{ {
fprintf(stderr, "uint16_from_uint8 is used only for backwards compatibility.\n"); fprintf(stderr, "uint16_from_uint8 is used only for backwards compatibility.\n");
fprintf(stderr, "Never should be used to write a new state.\n"); fprintf(stderr, "Never should be used to write a new state.\n");

View File

@ -583,7 +583,7 @@ static int get_uint32_as_uint16(QEMUFile *f, void *pv, size_t size,
} }
static int put_unused(QEMUFile *f, void *pv, size_t size, static int put_unused(QEMUFile *f, void *pv, size_t size,
const VMStateField *field, QJSON *vmdesc) const VMStateField *field, JSONWriter *vmdesc)
{ {
fprintf(stderr, "uint32_as_uint16 is only used for backward compatibility.\n"); fprintf(stderr, "uint32_as_uint16 is only used for backward compatibility.\n");
fprintf(stderr, "This functions shouldn't be called.\n"); fprintf(stderr, "This functions shouldn't be called.\n");

View File

@ -634,7 +634,7 @@ void msix_unset_vector_notifiers(PCIDevice *dev)
} }
static int put_msix_state(QEMUFile *f, void *pv, size_t size, static int put_msix_state(QEMUFile *f, void *pv, size_t size,
const VMStateField *field, QJSON *vmdesc) const VMStateField *field, JSONWriter *vmdesc)
{ {
msix_save(pv, f); msix_save(pv, f);

View File

@ -559,7 +559,7 @@ static int get_pci_config_device(QEMUFile *f, void *pv, size_t size,
/* just put buffer */ /* just put buffer */
static int put_pci_config_device(QEMUFile *f, void *pv, size_t size, static int put_pci_config_device(QEMUFile *f, void *pv, size_t size,
const VMStateField *field, QJSON *vmdesc) const VMStateField *field, JSONWriter *vmdesc)
{ {
const uint8_t **v = pv; const uint8_t **v = pv;
assert(size == pci_config_size(container_of(pv, PCIDevice, config))); assert(size == pci_config_size(container_of(pv, PCIDevice, config)));
@ -597,7 +597,7 @@ static int get_pci_irq_state(QEMUFile *f, void *pv, size_t size,
} }
static int put_pci_irq_state(QEMUFile *f, void *pv, size_t size, static int put_pci_irq_state(QEMUFile *f, void *pv, size_t size,
const VMStateField *field, QJSON *vmdesc) const VMStateField *field, JSONWriter *vmdesc)
{ {
int i; int i;
PCIDevice *s = container_of(pv, PCIDevice, irq_state); PCIDevice *s = container_of(pv, PCIDevice, irq_state);

View File

@ -699,7 +699,7 @@ void shpc_cap_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
} }
static int shpc_save(QEMUFile *f, void *pv, size_t size, static int shpc_save(QEMUFile *f, void *pv, size_t size,
const VMStateField *field, QJSON *vmdesc) const VMStateField *field, JSONWriter *vmdesc)
{ {
PCIDevice *d = container_of(pv, PCIDevice, shpc); PCIDevice *d = container_of(pv, PCIDevice, shpc);
qemu_put_buffer(f, d->shpc->config, SHPC_SIZEOF(d)); qemu_put_buffer(f, d->shpc->config, SHPC_SIZEOF(d));

View File

@ -78,7 +78,7 @@ static void clean_recv_mads(RdmaBackendDev *backend_dev)
unsigned long cqe_ctx_id; unsigned long cqe_ctx_id;
do { do {
cqe_ctx_id = rdma_protected_qlist_pop_int64(&backend_dev-> cqe_ctx_id = rdma_protected_gqueue_pop_int64(&backend_dev->
recv_mads_list); recv_mads_list);
if (cqe_ctx_id != -ENOENT) { if (cqe_ctx_id != -ENOENT) {
qatomic_inc(&backend_dev->rdma_dev_res->stats.missing_cqe); qatomic_inc(&backend_dev->rdma_dev_res->stats.missing_cqe);
@ -597,7 +597,7 @@ static unsigned int save_mad_recv_buffer(RdmaBackendDev *backend_dev,
bctx->up_ctx = ctx; bctx->up_ctx = ctx;
bctx->sge = *sge; bctx->sge = *sge;
rdma_protected_qlist_append_int64(&backend_dev->recv_mads_list, bctx_id); rdma_protected_gqueue_append_int64(&backend_dev->recv_mads_list, bctx_id);
return 0; return 0;
} }
@ -1111,7 +1111,7 @@ static void process_incoming_mad_req(RdmaBackendDev *backend_dev,
trace_mad_message("recv", msg->umad.mad, msg->umad_len); trace_mad_message("recv", msg->umad.mad, msg->umad_len);
cqe_ctx_id = rdma_protected_qlist_pop_int64(&backend_dev->recv_mads_list); cqe_ctx_id = rdma_protected_gqueue_pop_int64(&backend_dev->recv_mads_list);
if (cqe_ctx_id == -ENOENT) { if (cqe_ctx_id == -ENOENT) {
rdma_warn_report("No more free MADs buffers, waiting for a while"); rdma_warn_report("No more free MADs buffers, waiting for a while");
sleep(THR_POLL_TO); sleep(THR_POLL_TO);
@ -1185,7 +1185,7 @@ static int mad_init(RdmaBackendDev *backend_dev, CharBackend *mad_chr_be)
return -EIO; return -EIO;
} }
rdma_protected_qlist_init(&backend_dev->recv_mads_list); rdma_protected_gqueue_init(&backend_dev->recv_mads_list);
enable_rdmacm_mux_async(backend_dev); enable_rdmacm_mux_async(backend_dev);
@ -1205,7 +1205,7 @@ static void mad_fini(RdmaBackendDev *backend_dev)
{ {
disable_rdmacm_mux_async(backend_dev); disable_rdmacm_mux_async(backend_dev);
qemu_chr_fe_disconnect(backend_dev->rdmacm_mux.chr_be); qemu_chr_fe_disconnect(backend_dev->rdmacm_mux.chr_be);
rdma_protected_qlist_destroy(&backend_dev->recv_mads_list); rdma_protected_gqueue_destroy(&backend_dev->recv_mads_list);
} }
int rdma_backend_get_gid_index(RdmaBackendDev *backend_dev, int rdma_backend_get_gid_index(RdmaBackendDev *backend_dev,

View File

@ -43,7 +43,7 @@ typedef struct RdmaBackendDev {
struct ibv_context *context; struct ibv_context *context;
struct ibv_comp_channel *channel; struct ibv_comp_channel *channel;
uint8_t port_num; uint8_t port_num;
RdmaProtectedQList recv_mads_list; RdmaProtectedGQueue recv_mads_list;
RdmaCmMux rdmacm_mux; RdmaCmMux rdmacm_mux;
} RdmaBackendDev; } RdmaBackendDev;

View File

@ -14,8 +14,6 @@
*/ */
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "qapi/qmp/qlist.h"
#include "qapi/qmp/qnum.h"
#include "trace.h" #include "trace.h"
#include "rdma_utils.h" #include "rdma_utils.h"
@ -54,41 +52,46 @@ void rdma_pci_dma_unmap(PCIDevice *dev, void *buffer, dma_addr_t len)
} }
} }
void rdma_protected_qlist_init(RdmaProtectedQList *list) void rdma_protected_gqueue_init(RdmaProtectedGQueue *list)
{ {
qemu_mutex_init(&list->lock); qemu_mutex_init(&list->lock);
list->list = qlist_new(); list->list = g_queue_new();
} }
void rdma_protected_qlist_destroy(RdmaProtectedQList *list) void rdma_protected_gqueue_destroy(RdmaProtectedGQueue *list)
{ {
if (list->list) { if (list->list) {
qlist_destroy_obj(QOBJECT(list->list)); g_queue_free_full(list->list, g_free);
qemu_mutex_destroy(&list->lock); qemu_mutex_destroy(&list->lock);
list->list = NULL; list->list = NULL;
} }
} }
void rdma_protected_qlist_append_int64(RdmaProtectedQList *list, int64_t value) void rdma_protected_gqueue_append_int64(RdmaProtectedGQueue *list,
int64_t value)
{ {
qemu_mutex_lock(&list->lock); qemu_mutex_lock(&list->lock);
qlist_append_int(list->list, value); g_queue_push_tail(list->list, g_memdup(&value, sizeof(value)));
qemu_mutex_unlock(&list->lock); qemu_mutex_unlock(&list->lock);
} }
int64_t rdma_protected_qlist_pop_int64(RdmaProtectedQList *list) int64_t rdma_protected_gqueue_pop_int64(RdmaProtectedGQueue *list)
{ {
QObject *obj; int64_t *valp;
int64_t val;
qemu_mutex_lock(&list->lock); qemu_mutex_lock(&list->lock);
obj = qlist_pop(list->list);
valp = g_queue_pop_head(list->list);
qemu_mutex_unlock(&list->lock); qemu_mutex_unlock(&list->lock);
if (!obj) { if (!valp) {
return -ENOENT; return -ENOENT;
} }
return qnum_get_uint(qobject_to(QNum, obj)); val = *valp;
g_free(valp);
return val;
} }
void rdma_protected_gslist_init(RdmaProtectedGSList *list) void rdma_protected_gslist_init(RdmaProtectedGSList *list)

View File

@ -28,10 +28,10 @@
#define rdma_info_report(fmt, ...) \ #define rdma_info_report(fmt, ...) \
info_report("%s: " fmt, "rdma", ## __VA_ARGS__) info_report("%s: " fmt, "rdma", ## __VA_ARGS__)
typedef struct RdmaProtectedQList { typedef struct RdmaProtectedGQueue {
QemuMutex lock; QemuMutex lock;
QList *list; GQueue *list;
} RdmaProtectedQList; } RdmaProtectedGQueue;
typedef struct RdmaProtectedGSList { typedef struct RdmaProtectedGSList {
QemuMutex lock; QemuMutex lock;
@ -40,10 +40,11 @@ typedef struct RdmaProtectedGSList {
void *rdma_pci_dma_map(PCIDevice *dev, dma_addr_t addr, dma_addr_t plen); void *rdma_pci_dma_map(PCIDevice *dev, dma_addr_t addr, dma_addr_t plen);
void rdma_pci_dma_unmap(PCIDevice *dev, void *buffer, dma_addr_t len); void rdma_pci_dma_unmap(PCIDevice *dev, void *buffer, dma_addr_t len);
void rdma_protected_qlist_init(RdmaProtectedQList *list); void rdma_protected_gqueue_init(RdmaProtectedGQueue *list);
void rdma_protected_qlist_destroy(RdmaProtectedQList *list); void rdma_protected_gqueue_destroy(RdmaProtectedGQueue *list);
void rdma_protected_qlist_append_int64(RdmaProtectedQList *list, int64_t value); void rdma_protected_gqueue_append_int64(RdmaProtectedGQueue *list,
int64_t rdma_protected_qlist_pop_int64(RdmaProtectedQList *list); int64_t value);
int64_t rdma_protected_gqueue_pop_int64(RdmaProtectedGQueue *list);
void rdma_protected_gslist_init(RdmaProtectedGSList *list); void rdma_protected_gslist_init(RdmaProtectedGSList *list);
void rdma_protected_gslist_destroy(RdmaProtectedGSList *list); void rdma_protected_gslist_destroy(RdmaProtectedGSList *list);
void rdma_protected_gslist_append_int32(RdmaProtectedGSList *list, void rdma_protected_gslist_append_int32(RdmaProtectedGSList *list,

View File

@ -746,7 +746,7 @@ static int get_int32_as_uint16(QEMUFile *f, void *pv, size_t size,
} }
static int put_int32_as_uint16(QEMUFile *f, void *pv, size_t size, static int put_int32_as_uint16(QEMUFile *f, void *pv, size_t size,
const VMStateField *field, QJSON *vmdesc) const VMStateField *field, JSONWriter *vmdesc)
{ {
int *v = pv; int *v = pv;
qemu_put_be16(f, *v); qemu_put_be16(f, *v);

View File

@ -1638,7 +1638,7 @@ static char *scsibus_get_fw_dev_path(DeviceState *dev)
/* SCSI request list. For simplicity, pv points to the whole device */ /* SCSI request list. For simplicity, pv points to the whole device */
static int put_scsi_requests(QEMUFile *f, void *pv, size_t size, static int put_scsi_requests(QEMUFile *f, void *pv, size_t size,
const VMStateField *field, QJSON *vmdesc) const VMStateField *field, JSONWriter *vmdesc)
{ {
SCSIDevice *s = pv; SCSIDevice *s = pv;
SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, s->qdev.parent_bus); SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, s->qdev.parent_bus);

View File

@ -2227,7 +2227,7 @@ static int usbredir_post_load(void *priv, int version_id)
/* For usbredirparser migration */ /* For usbredirparser migration */
static int usbredir_put_parser(QEMUFile *f, void *priv, size_t unused, static int usbredir_put_parser(QEMUFile *f, void *priv, size_t unused,
const VMStateField *field, QJSON *vmdesc) const VMStateField *field, JSONWriter *vmdesc)
{ {
USBRedirDevice *dev = priv; USBRedirDevice *dev = priv;
uint8_t *data; uint8_t *data;
@ -2294,7 +2294,7 @@ static const VMStateInfo usbredir_parser_vmstate_info = {
/* For buffered packets (iso/irq) queue migration */ /* For buffered packets (iso/irq) queue migration */
static int usbredir_put_bufpq(QEMUFile *f, void *priv, size_t unused, static int usbredir_put_bufpq(QEMUFile *f, void *priv, size_t unused,
const VMStateField *field, QJSON *vmdesc) const VMStateField *field, JSONWriter *vmdesc)
{ {
struct endp_data *endp = priv; struct endp_data *endp = priv;
USBRedirDevice *dev = endp->dev; USBRedirDevice *dev = endp->dev;
@ -2421,7 +2421,8 @@ static const VMStateDescription usbredir_ep_vmstate = {
/* For PacketIdQueue migration */ /* For PacketIdQueue migration */
static int usbredir_put_packet_id_q(QEMUFile *f, void *priv, size_t unused, static int usbredir_put_packet_id_q(QEMUFile *f, void *priv, size_t unused,
const VMStateField *field, QJSON *vmdesc) const VMStateField *field,
JSONWriter *vmdesc)
{ {
struct PacketIdQueue *q = priv; struct PacketIdQueue *q = priv;
USBRedirDevice *dev = q->dev; USBRedirDevice *dev = q->dev;

View File

@ -2745,7 +2745,7 @@ static int get_extra_state(QEMUFile *f, void *pv, size_t size,
} }
static int put_extra_state(QEMUFile *f, void *pv, size_t size, static int put_extra_state(QEMUFile *f, void *pv, size_t size,
const VMStateField *field, QJSON *vmdesc) const VMStateField *field, JSONWriter *vmdesc)
{ {
VirtIODevice *vdev = pv; VirtIODevice *vdev = pv;
BusState *qbus = qdev_get_parent_bus(DEVICE(vdev)); BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
@ -2919,7 +2919,7 @@ int virtio_save(VirtIODevice *vdev, QEMUFile *f)
/* A wrapper for use as a VMState .put function */ /* A wrapper for use as a VMState .put function */
static int virtio_device_put(QEMUFile *f, void *opaque, size_t size, static int virtio_device_put(QEMUFile *f, void *opaque, size_t size,
const VMStateField *field, QJSON *vmdesc) const VMStateField *field, JSONWriter *vmdesc)
{ {
return virtio_save(VIRTIO_DEVICE(opaque), f); return virtio_save(VIRTIO_DEVICE(opaque), f);
} }

View File

@ -43,7 +43,7 @@ struct VMStateInfo {
const char *name; const char *name;
int (*get)(QEMUFile *f, void *pv, size_t size, const VMStateField *field); int (*get)(QEMUFile *f, void *pv, size_t size, const VMStateField *field);
int (*put)(QEMUFile *f, void *pv, size_t size, const VMStateField *field, int (*put)(QEMUFile *f, void *pv, size_t size, const VMStateField *field,
QJSON *vmdesc); JSONWriter *vmdesc);
}; };
enum VMStateFlags { enum VMStateFlags {
@ -1169,9 +1169,10 @@ extern const VMStateInfo vmstate_info_qlist;
int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd, int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
void *opaque, int version_id); void *opaque, int version_id);
int vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd, int vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
void *opaque, QJSON *vmdesc); void *opaque, JSONWriter *vmdesc);
int vmstate_save_state_v(QEMUFile *f, const VMStateDescription *vmsd, int vmstate_save_state_v(QEMUFile *f, const VMStateDescription *vmsd,
void *opaque, QJSON *vmdesc, int version_id); void *opaque, JSONWriter *vmdesc,
int version_id);
bool vmstate_save_needed(const VMStateDescription *vmsd, void *opaque); bool vmstate_save_needed(const VMStateDescription *vmsd, void *opaque);

View File

@ -0,0 +1,35 @@
/*
* JSON Writer
*
* Copyright (c) 2020 Red Hat Inc.
*
* Authors:
* Markus Armbruster <armbru@redhat.com>
*
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
* See the COPYING.LIB file in the top-level directory.
*
*/
#ifndef JSON_WRITER_H
#define JSON_WRITER_H
JSONWriter *json_writer_new(bool pretty);
const char *json_writer_get(JSONWriter *);
GString *json_writer_get_and_free(JSONWriter *);
void json_writer_free(JSONWriter *);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(JSONWriter, json_writer_free)
void json_writer_start_object(JSONWriter *, const char *name);
void json_writer_end_object(JSONWriter *);
void json_writer_start_array(JSONWriter *, const char *name);
void json_writer_end_array(JSONWriter *);
void json_writer_bool(JSONWriter *, const char *name, bool val);
void json_writer_null(JSONWriter *, const char *name);
void json_writer_int64(JSONWriter *, const char *name, int64_t val);
void json_writer_uint64(JSONWriter *, const char *name, uint64_t val);
void json_writer_double(JSONWriter *, const char *name, double val);
void json_writer_str(JSONWriter *, const char *name, const char *str);
#endif

View File

@ -23,7 +23,5 @@ struct QBool {
QBool *qbool_from_bool(bool value); QBool *qbool_from_bool(bool value);
bool qbool_get_bool(const QBool *qb); bool qbool_get_bool(const QBool *qb);
bool qbool_is_equal(const QObject *x, const QObject *y);
void qbool_destroy_obj(QObject *obj);
#endif /* QBOOL_H */ #endif /* QBOOL_H */

View File

@ -39,10 +39,8 @@ void qdict_put_obj(QDict *qdict, const char *key, QObject *value);
void qdict_del(QDict *qdict, const char *key); void qdict_del(QDict *qdict, const char *key);
int qdict_haskey(const QDict *qdict, const char *key); int qdict_haskey(const QDict *qdict, const char *key);
QObject *qdict_get(const QDict *qdict, const char *key); QObject *qdict_get(const QDict *qdict, const char *key);
bool qdict_is_equal(const QObject *x, const QObject *y);
const QDictEntry *qdict_first(const QDict *qdict); const QDictEntry *qdict_first(const QDict *qdict);
const QDictEntry *qdict_next(const QDict *qdict, const QDictEntry *entry); const QDictEntry *qdict_next(const QDict *qdict, const QDictEntry *entry);
void qdict_destroy_obj(QObject *obj);
/* Helper to qdict_put_obj(), accepts any object */ /* Helper to qdict_put_obj(), accepts any object */
#define qdict_put(qdict, key, obj) \ #define qdict_put(qdict, key, obj) \

View File

@ -25,7 +25,7 @@ QDict *qdict_from_vjsonf_nofail(const char *string, va_list ap)
QDict *qdict_from_jsonf_nofail(const char *string, ...) QDict *qdict_from_jsonf_nofail(const char *string, ...)
GCC_FMT_ATTR(1, 2); GCC_FMT_ATTR(1, 2);
QString *qobject_to_json(const QObject *obj); GString *qobject_to_json(const QObject *obj);
QString *qobject_to_json_pretty(const QObject *obj); GString *qobject_to_json_pretty(const QObject *obj, bool pretty);
#endif /* QJSON_H */ #endif /* QJSON_H */

View File

@ -51,8 +51,6 @@ QObject *qlist_pop(QList *qlist);
QObject *qlist_peek(QList *qlist); QObject *qlist_peek(QList *qlist);
int qlist_empty(const QList *qlist); int qlist_empty(const QList *qlist);
size_t qlist_size(const QList *qlist); size_t qlist_size(const QList *qlist);
bool qlist_is_equal(const QObject *x, const QObject *y);
void qlist_destroy_obj(QObject *obj);
static inline const QListEntry *qlist_first(const QList *qlist) static inline const QListEntry *qlist_first(const QList *qlist)
{ {

View File

@ -26,6 +26,4 @@ static inline QNull *qnull(void)
return qobject_ref(&qnull_); return qobject_ref(&qnull_);
} }
bool qnull_is_equal(const QObject *x, const QObject *y);
#endif /* QNULL_H */ #endif /* QNULL_H */

View File

@ -68,7 +68,4 @@ double qnum_get_double(QNum *qn);
char *qnum_to_string(QNum *qn); char *qnum_to_string(QNum *qn);
bool qnum_is_equal(const QObject *x, const QObject *y);
void qnum_destroy_obj(QObject *obj);
#endif /* QNUM_H */ #endif /* QNUM_H */

View File

@ -64,14 +64,6 @@ QEMU_BUILD_BUG_MSG(QTYPE__MAX != 7,
#define qobject_to(type, obj) \ #define qobject_to(type, obj) \
((type *)qobject_check_type(obj, glue(QTYPE_CAST_TO_, type))) ((type *)qobject_check_type(obj, glue(QTYPE_CAST_TO_, type)))
/* Initialize an object to default values */
static inline void qobject_init(QObject *obj, QType type)
{
assert(QTYPE_NONE < type && type < QTYPE__MAX);
obj->base.refcnt = 1;
obj->base.type = type;
}
static inline void qobject_ref_impl(QObject *obj) static inline void qobject_ref_impl(QObject *obj)
{ {
if (obj) { if (obj) {
@ -90,6 +82,7 @@ bool qobject_is_equal(const QObject *x, const QObject *y);
/** /**
* qobject_destroy(): Free resources used by the object * qobject_destroy(): Free resources used by the object
* For use via qobject_unref() only!
*/ */
void qobject_destroy(QObject *obj); void qobject_destroy(QObject *obj);

View File

@ -17,23 +17,13 @@
struct QString { struct QString {
struct QObjectBase_ base; struct QObjectBase_ base;
char *string; const char *string;
size_t length;
size_t capacity;
}; };
QString *qstring_new(void); QString *qstring_new(void);
QString *qstring_from_str(const char *str); QString *qstring_from_str(const char *str);
QString *qstring_from_substr(const char *str, size_t start, size_t end); QString *qstring_from_substr(const char *str, size_t start, size_t end);
size_t qstring_get_length(const QString *qstring); QString *qstring_from_gstring(GString *gstr);
const char *qstring_get_str(const QString *qstring); const char *qstring_get_str(const QString *qstring);
const char *qstring_get_try_str(const QString *qstring);
const char *qobject_get_try_str(const QObject *qstring);
void qstring_append_int(QString *qstring, int64_t value);
void qstring_append(QString *qstring, const char *str);
void qstring_append_chr(QString *qstring, int c);
bool qstring_is_equal(const QObject *x, const QObject *y);
char *qstring_free(QString *qstring, bool return_str);
void qstring_destroy_obj(QObject *obj);
#endif /* QSTRING_H */ #endif /* QSTRING_H */

View File

@ -57,8 +57,8 @@ typedef struct IOMMUMemoryRegion IOMMUMemoryRegion;
typedef struct ISABus ISABus; typedef struct ISABus ISABus;
typedef struct ISADevice ISADevice; typedef struct ISADevice ISADevice;
typedef struct IsaDma IsaDma; typedef struct IsaDma IsaDma;
typedef struct JSONWriter JSONWriter;
typedef struct MACAddr MACAddr; typedef struct MACAddr MACAddr;
typedef struct ReservedRegion ReservedRegion;
typedef struct MachineClass MachineClass; typedef struct MachineClass MachineClass;
typedef struct MachineState MachineState; typedef struct MachineState MachineState;
typedef struct MemoryListener MemoryListener; typedef struct MemoryListener MemoryListener;
@ -107,7 +107,6 @@ typedef struct QEMUSGList QEMUSGList;
typedef struct QemuSpin QemuSpin; typedef struct QemuSpin QemuSpin;
typedef struct QEMUTimer QEMUTimer; typedef struct QEMUTimer QEMUTimer;
typedef struct QEMUTimerListGroup QEMUTimerListGroup; typedef struct QEMUTimerListGroup QEMUTimerListGroup;
typedef struct QJSON QJSON;
typedef struct QList QList; typedef struct QList QList;
typedef struct QNull QNull; typedef struct QNull QNull;
typedef struct QNum QNum; typedef struct QNum QNum;
@ -115,6 +114,7 @@ typedef struct QObject QObject;
typedef struct QString QString; typedef struct QString QString;
typedef struct RAMBlock RAMBlock; typedef struct RAMBlock RAMBlock;
typedef struct Range Range; typedef struct Range Range;
typedef struct ReservedRegion ReservedRegion;
typedef struct SavedIOTLB SavedIOTLB; typedef struct SavedIOTLB SavedIOTLB;
typedef struct SHPCDevice SHPCDevice; typedef struct SHPCDevice SHPCDevice;
typedef struct SSIBus SSIBus; typedef struct SSIBus SSIBus;

View File

@ -6,7 +6,6 @@ migration_files = files(
'vmstate.c', 'vmstate.c',
'qemu-file-channel.c', 'qemu-file-channel.c',
'qemu-file.c', 'qemu-file.c',
'qjson.c',
) )
softmmu_ss.add(migration_files) softmmu_ss.add(migration_files)

View File

@ -406,12 +406,9 @@ int migration_incoming_enable_colo(void)
void migrate_add_address(SocketAddress *address) void migrate_add_address(SocketAddress *address)
{ {
MigrationIncomingState *mis = migration_incoming_get_current(); MigrationIncomingState *mis = migration_incoming_get_current();
SocketAddressList *addrs;
addrs = g_new0(SocketAddressList, 1); QAPI_LIST_PREPEND(mis->socket_address_list,
addrs->next = mis->socket_address_list; QAPI_CLONE(SocketAddress, address));
mis->socket_address_list = addrs;
addrs->value = QAPI_CLONE(SocketAddress, address);
} }
static void qemu_start_incoming_migration(const char *uri, Error **errp) static void qemu_start_incoming_migration(const char *uri, Error **errp)
@ -1654,27 +1651,23 @@ void migrate_set_state(int *state, int old_state, int new_state)
} }
} }
static MigrationCapabilityStatusList *migrate_cap_add( static MigrationCapabilityStatus *migrate_cap_add(MigrationCapability index,
MigrationCapabilityStatusList *list, bool state)
MigrationCapability index,
bool state)
{ {
MigrationCapabilityStatusList *cap; MigrationCapabilityStatus *cap;
cap = g_new0(MigrationCapabilityStatusList, 1); cap = g_new0(MigrationCapabilityStatus, 1);
cap->value = g_new0(MigrationCapabilityStatus, 1); cap->capability = index;
cap->value->capability = index; cap->state = state;
cap->value->state = state;
cap->next = list;
return cap; return cap;
} }
void migrate_set_block_enabled(bool value, Error **errp) void migrate_set_block_enabled(bool value, Error **errp)
{ {
MigrationCapabilityStatusList *cap; MigrationCapabilityStatusList *cap = NULL;
cap = migrate_cap_add(NULL, MIGRATION_CAPABILITY_BLOCK, value); QAPI_LIST_PREPEND(cap, migrate_cap_add(MIGRATION_CAPABILITY_BLOCK, value));
qmp_migrate_set_capabilities(cap, errp); qmp_migrate_set_capabilities(cap, errp);
qapi_free_MigrationCapabilityStatusList(cap); qapi_free_MigrationCapabilityStatusList(cap);
} }
@ -3869,7 +3862,7 @@ static bool migration_object_check(MigrationState *ms, Error **errp)
for (i = 0; i < MIGRATION_CAPABILITY__MAX; i++) { for (i = 0; i < MIGRATION_CAPABILITY__MAX; i++) {
if (ms->enabled_capabilities[i]) { if (ms->enabled_capabilities[i]) {
head = migrate_cap_add(head, i, true); QAPI_LIST_PREPEND(head, migrate_cap_add(i, true));
} }
} }

View File

@ -145,14 +145,11 @@ static struct PostcopyBlocktimeContext *blocktime_context_new(void)
static uint32List *get_vcpu_blocktime_list(PostcopyBlocktimeContext *ctx) static uint32List *get_vcpu_blocktime_list(PostcopyBlocktimeContext *ctx)
{ {
MachineState *ms = MACHINE(qdev_get_machine()); MachineState *ms = MACHINE(qdev_get_machine());
uint32List *list = NULL, *entry = NULL; uint32List *list = NULL;
int i; int i;
for (i = ms->smp.cpus - 1; i >= 0; i--) { for (i = ms->smp.cpus - 1; i >= 0; i--) {
entry = g_new0(uint32List, 1); QAPI_LIST_PREPEND(list, ctx->vcpu_blocktime[i]);
entry->value = ctx->vcpu_blocktime[i];
entry->next = list;
list = entry;
} }
return list; return list;

View File

@ -1,114 +0,0 @@
/*
* A simple JSON writer
*
* Copyright Alexander Graf
*
* Authors:
* Alexander Graf <agraf@suse.de>
*
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
* See the COPYING.LIB file in the top-level directory.
*
*/
/*
* Type QJSON lets you build JSON text. Its interface mirrors (a
* subset of) abstract JSON syntax.
*
* It does *not* detect incorrect use. It happily produces invalid
* JSON then. This is what migration wants.
*
* QAPI output visitors also produce JSON text. However, they do
* assert their preconditions and invariants, and therefore abort on
* incorrect use.
*/
#include "qemu/osdep.h"
#include "qapi/qmp/qstring.h"
#include "qjson.h"
struct QJSON {
QString *str;
bool omit_comma;
};
static void json_emit_element(QJSON *json, const char *name)
{
/* Check whether we need to print a , before an element */
if (json->omit_comma) {
json->omit_comma = false;
} else {
qstring_append(json->str, ", ");
}
if (name) {
qstring_append(json->str, "\"");
qstring_append(json->str, name);
qstring_append(json->str, "\" : ");
}
}
void json_start_object(QJSON *json, const char *name)
{
json_emit_element(json, name);
qstring_append(json->str, "{ ");
json->omit_comma = true;
}
void json_end_object(QJSON *json)
{
qstring_append(json->str, " }");
json->omit_comma = false;
}
void json_start_array(QJSON *json, const char *name)
{
json_emit_element(json, name);
qstring_append(json->str, "[ ");
json->omit_comma = true;
}
void json_end_array(QJSON *json)
{
qstring_append(json->str, " ]");
json->omit_comma = false;
}
void json_prop_int(QJSON *json, const char *name, int64_t val)
{
json_emit_element(json, name);
qstring_append_int(json->str, val);
}
void json_prop_str(QJSON *json, const char *name, const char *str)
{
json_emit_element(json, name);
qstring_append_chr(json->str, '"');
qstring_append(json->str, str);
qstring_append_chr(json->str, '"');
}
const char *qjson_get_str(QJSON *json)
{
return qstring_get_str(json->str);
}
QJSON *qjson_new(void)
{
QJSON *json = g_new0(QJSON, 1);
json->str = qstring_from_str("{ ");
json->omit_comma = true;
return json;
}
void qjson_finish(QJSON *json)
{
json_end_object(json);
}
void qjson_destroy(QJSON *json)
{
qobject_unref(json->str);
g_free(json);
}

View File

@ -1,29 +0,0 @@
/*
* QEMU JSON writer
*
* Copyright Alexander Graf
*
* Authors:
* Alexander Graf <agraf@suse.de>
*
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
* See the COPYING.LIB file in the top-level directory.
*
*/
#ifndef QEMU_QJSON_H
#define QEMU_QJSON_H
QJSON *qjson_new(void);
void qjson_destroy(QJSON *json);
void json_prop_str(QJSON *json, const char *name, const char *str);
void json_prop_int(QJSON *json, const char *name, int64_t val);
void json_end_array(QJSON *json);
void json_start_array(QJSON *json, const char *name);
void json_end_object(QJSON *json);
void json_start_object(QJSON *json, const char *name);
const char *qjson_get_str(QJSON *json);
void qjson_finish(QJSON *json);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(QJSON, qjson_destroy)
#endif /* QEMU_QJSON_H */

View File

@ -42,6 +42,7 @@
#include "postcopy-ram.h" #include "postcopy-ram.h"
#include "qapi/error.h" #include "qapi/error.h"
#include "qapi/qapi-commands-migration.h" #include "qapi/qapi-commands-migration.h"
#include "qapi/qmp/json-writer.h"
#include "qapi/qmp/qerror.h" #include "qapi/qmp/qerror.h"
#include "qemu/error-report.h" #include "qemu/error-report.h"
#include "sysemu/cpus.h" #include "sysemu/cpus.h"
@ -58,7 +59,6 @@
#include "sysemu/runstate.h" #include "sysemu/runstate.h"
#include "sysemu/sysemu.h" #include "sysemu/sysemu.h"
#include "sysemu/xen.h" #include "sysemu/xen.h"
#include "qjson.h"
#include "migration/colo.h" #include "migration/colo.h"
#include "qemu/bitmap.h" #include "qemu/bitmap.h"
#include "net/announce.h" #include "net/announce.h"
@ -209,7 +209,7 @@ static int get_timer(QEMUFile *f, void *pv, size_t size,
} }
static int put_timer(QEMUFile *f, void *pv, size_t size, static int put_timer(QEMUFile *f, void *pv, size_t size,
const VMStateField *field, QJSON *vmdesc) const VMStateField *field, JSONWriter *vmdesc)
{ {
QEMUTimer *v = pv; QEMUTimer *v = pv;
timer_put(f, v); timer_put(f, v);
@ -406,7 +406,7 @@ static int get_capability(QEMUFile *f, void *pv, size_t size,
} }
static int put_capability(QEMUFile *f, void *pv, size_t size, static int put_capability(QEMUFile *f, void *pv, size_t size,
const VMStateField *field, QJSON *vmdesc) const VMStateField *field, JSONWriter *vmdesc)
{ {
MigrationCapability *capability = pv; MigrationCapability *capability = pv;
const char *capability_str = MigrationCapability_str(*capability); const char *capability_str = MigrationCapability_str(*capability);
@ -884,7 +884,8 @@ static int vmstate_load(QEMUFile *f, SaveStateEntry *se)
return vmstate_load_state(f, se->vmsd, se->opaque, se->load_version_id); return vmstate_load_state(f, se->vmsd, se->opaque, se->load_version_id);
} }
static void vmstate_save_old_style(QEMUFile *f, SaveStateEntry *se, QJSON *vmdesc) static void vmstate_save_old_style(QEMUFile *f, SaveStateEntry *se,
JSONWriter *vmdesc)
{ {
int64_t old_offset, size; int64_t old_offset, size;
@ -893,18 +894,19 @@ static void vmstate_save_old_style(QEMUFile *f, SaveStateEntry *se, QJSON *vmdes
size = qemu_ftell_fast(f) - old_offset; size = qemu_ftell_fast(f) - old_offset;
if (vmdesc) { if (vmdesc) {
json_prop_int(vmdesc, "size", size); json_writer_int64(vmdesc, "size", size);
json_start_array(vmdesc, "fields"); json_writer_start_array(vmdesc, "fields");
json_start_object(vmdesc, NULL); json_writer_start_object(vmdesc, NULL);
json_prop_str(vmdesc, "name", "data"); json_writer_str(vmdesc, "name", "data");
json_prop_int(vmdesc, "size", size); json_writer_int64(vmdesc, "size", size);
json_prop_str(vmdesc, "type", "buffer"); json_writer_str(vmdesc, "type", "buffer");
json_end_object(vmdesc); json_writer_end_object(vmdesc);
json_end_array(vmdesc); json_writer_end_array(vmdesc);
} }
} }
static int vmstate_save(QEMUFile *f, SaveStateEntry *se, QJSON *vmdesc) static int vmstate_save(QEMUFile *f, SaveStateEntry *se,
JSONWriter *vmdesc)
{ {
trace_vmstate_save(se->idstr, se->vmsd ? se->vmsd->name : "(old)"); trace_vmstate_save(se->idstr, se->vmsd ? se->vmsd->name : "(old)");
if (!se->vmsd) { if (!se->vmsd) {
@ -1357,14 +1359,15 @@ int qemu_savevm_state_complete_precopy_non_iterable(QEMUFile *f,
bool in_postcopy, bool in_postcopy,
bool inactivate_disks) bool inactivate_disks)
{ {
g_autoptr(QJSON) vmdesc = NULL; g_autoptr(JSONWriter) vmdesc = NULL;
int vmdesc_len; int vmdesc_len;
SaveStateEntry *se; SaveStateEntry *se;
int ret; int ret;
vmdesc = qjson_new(); vmdesc = json_writer_new(false);
json_prop_int(vmdesc, "page_size", qemu_target_page_size()); json_writer_start_object(vmdesc, NULL);
json_start_array(vmdesc, "devices"); json_writer_int64(vmdesc, "page_size", qemu_target_page_size());
json_writer_start_array(vmdesc, "devices");
QTAILQ_FOREACH(se, &savevm_state.handlers, entry) { QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
if ((!se->ops || !se->ops->save_state) && !se->vmsd) { if ((!se->ops || !se->ops->save_state) && !se->vmsd) {
@ -1377,9 +1380,9 @@ int qemu_savevm_state_complete_precopy_non_iterable(QEMUFile *f,
trace_savevm_section_start(se->idstr, se->section_id); trace_savevm_section_start(se->idstr, se->section_id);
json_start_object(vmdesc, NULL); json_writer_start_object(vmdesc, NULL);
json_prop_str(vmdesc, "name", se->idstr); json_writer_str(vmdesc, "name", se->idstr);
json_prop_int(vmdesc, "instance_id", se->instance_id); json_writer_int64(vmdesc, "instance_id", se->instance_id);
save_section_header(f, se, QEMU_VM_SECTION_FULL); save_section_header(f, se, QEMU_VM_SECTION_FULL);
ret = vmstate_save(f, se, vmdesc); ret = vmstate_save(f, se, vmdesc);
@ -1390,7 +1393,7 @@ int qemu_savevm_state_complete_precopy_non_iterable(QEMUFile *f,
trace_savevm_section_end(se->idstr, se->section_id, 0); trace_savevm_section_end(se->idstr, se->section_id, 0);
save_section_footer(f, se); save_section_footer(f, se);
json_end_object(vmdesc); json_writer_end_object(vmdesc);
} }
if (inactivate_disks) { if (inactivate_disks) {
@ -1409,14 +1412,14 @@ int qemu_savevm_state_complete_precopy_non_iterable(QEMUFile *f,
qemu_put_byte(f, QEMU_VM_EOF); qemu_put_byte(f, QEMU_VM_EOF);
} }
json_end_array(vmdesc); json_writer_end_array(vmdesc);
qjson_finish(vmdesc); json_writer_end_object(vmdesc);
vmdesc_len = strlen(qjson_get_str(vmdesc)); vmdesc_len = strlen(json_writer_get(vmdesc));
if (should_send_vmdesc()) { if (should_send_vmdesc()) {
qemu_put_byte(f, QEMU_VM_VMDESCRIPTION); qemu_put_byte(f, QEMU_VM_VMDESCRIPTION);
qemu_put_be32(f, vmdesc_len); qemu_put_be32(f, vmdesc_len);
qemu_put_buffer(f, (uint8_t *)qjson_get_str(vmdesc), vmdesc_len); qemu_put_buffer(f, (uint8_t *)json_writer_get(vmdesc), vmdesc_len);
} }
return 0; return 0;

View File

@ -29,7 +29,7 @@ static int get_bool(QEMUFile *f, void *pv, size_t size,
} }
static int put_bool(QEMUFile *f, void *pv, size_t size, static int put_bool(QEMUFile *f, void *pv, size_t size,
const VMStateField *field, QJSON *vmdesc) const VMStateField *field, JSONWriter *vmdesc)
{ {
bool *v = pv; bool *v = pv;
qemu_put_byte(f, *v); qemu_put_byte(f, *v);
@ -53,7 +53,7 @@ static int get_int8(QEMUFile *f, void *pv, size_t size,
} }
static int put_int8(QEMUFile *f, void *pv, size_t size, static int put_int8(QEMUFile *f, void *pv, size_t size,
const VMStateField *field, QJSON *vmdesc) const VMStateField *field, JSONWriter *vmdesc)
{ {
int8_t *v = pv; int8_t *v = pv;
qemu_put_s8s(f, v); qemu_put_s8s(f, v);
@ -77,7 +77,7 @@ static int get_int16(QEMUFile *f, void *pv, size_t size,
} }
static int put_int16(QEMUFile *f, void *pv, size_t size, static int put_int16(QEMUFile *f, void *pv, size_t size,
const VMStateField *field, QJSON *vmdesc) const VMStateField *field, JSONWriter *vmdesc)
{ {
int16_t *v = pv; int16_t *v = pv;
qemu_put_sbe16s(f, v); qemu_put_sbe16s(f, v);
@ -101,7 +101,7 @@ static int get_int32(QEMUFile *f, void *pv, size_t size,
} }
static int put_int32(QEMUFile *f, void *pv, size_t size, static int put_int32(QEMUFile *f, void *pv, size_t size,
const VMStateField *field, QJSON *vmdesc) const VMStateField *field, JSONWriter *vmdesc)
{ {
int32_t *v = pv; int32_t *v = pv;
qemu_put_sbe32s(f, v); qemu_put_sbe32s(f, v);
@ -178,7 +178,7 @@ static int get_int64(QEMUFile *f, void *pv, size_t size,
} }
static int put_int64(QEMUFile *f, void *pv, size_t size, static int put_int64(QEMUFile *f, void *pv, size_t size,
const VMStateField *field, QJSON *vmdesc) const VMStateField *field, JSONWriter *vmdesc)
{ {
int64_t *v = pv; int64_t *v = pv;
qemu_put_sbe64s(f, v); qemu_put_sbe64s(f, v);
@ -202,7 +202,7 @@ static int get_uint8(QEMUFile *f, void *pv, size_t size,
} }
static int put_uint8(QEMUFile *f, void *pv, size_t size, static int put_uint8(QEMUFile *f, void *pv, size_t size,
const VMStateField *field, QJSON *vmdesc) const VMStateField *field, JSONWriter *vmdesc)
{ {
uint8_t *v = pv; uint8_t *v = pv;
qemu_put_8s(f, v); qemu_put_8s(f, v);
@ -226,7 +226,7 @@ static int get_uint16(QEMUFile *f, void *pv, size_t size,
} }
static int put_uint16(QEMUFile *f, void *pv, size_t size, static int put_uint16(QEMUFile *f, void *pv, size_t size,
const VMStateField *field, QJSON *vmdesc) const VMStateField *field, JSONWriter *vmdesc)
{ {
uint16_t *v = pv; uint16_t *v = pv;
qemu_put_be16s(f, v); qemu_put_be16s(f, v);
@ -250,7 +250,7 @@ static int get_uint32(QEMUFile *f, void *pv, size_t size,
} }
static int put_uint32(QEMUFile *f, void *pv, size_t size, static int put_uint32(QEMUFile *f, void *pv, size_t size,
const VMStateField *field, QJSON *vmdesc) const VMStateField *field, JSONWriter *vmdesc)
{ {
uint32_t *v = pv; uint32_t *v = pv;
qemu_put_be32s(f, v); qemu_put_be32s(f, v);
@ -300,7 +300,7 @@ static int get_uint64(QEMUFile *f, void *pv, size_t size,
} }
static int put_uint64(QEMUFile *f, void *pv, size_t size, static int put_uint64(QEMUFile *f, void *pv, size_t size,
const VMStateField *field, QJSON *vmdesc) const VMStateField *field, JSONWriter *vmdesc)
{ {
uint64_t *v = pv; uint64_t *v = pv;
qemu_put_be64s(f, v); qemu_put_be64s(f, v);
@ -325,7 +325,7 @@ static int get_nullptr(QEMUFile *f, void *pv, size_t size,
} }
static int put_nullptr(QEMUFile *f, void *pv, size_t size, static int put_nullptr(QEMUFile *f, void *pv, size_t size,
const VMStateField *field, QJSON *vmdesc) const VMStateField *field, JSONWriter *vmdesc)
{ {
if (pv == NULL) { if (pv == NULL) {
@ -432,7 +432,7 @@ static int get_cpudouble(QEMUFile *f, void *pv, size_t size,
} }
static int put_cpudouble(QEMUFile *f, void *pv, size_t size, static int put_cpudouble(QEMUFile *f, void *pv, size_t size,
const VMStateField *field, QJSON *vmdesc) const VMStateField *field, JSONWriter *vmdesc)
{ {
CPU_DoubleU *v = pv; CPU_DoubleU *v = pv;
qemu_put_be32s(f, &v->l.upper); qemu_put_be32s(f, &v->l.upper);
@ -457,7 +457,7 @@ static int get_buffer(QEMUFile *f, void *pv, size_t size,
} }
static int put_buffer(QEMUFile *f, void *pv, size_t size, static int put_buffer(QEMUFile *f, void *pv, size_t size,
const VMStateField *field, QJSON *vmdesc) const VMStateField *field, JSONWriter *vmdesc)
{ {
uint8_t *v = pv; uint8_t *v = pv;
qemu_put_buffer(f, v, size); qemu_put_buffer(f, v, size);
@ -488,7 +488,7 @@ static int get_unused_buffer(QEMUFile *f, void *pv, size_t size,
} }
static int put_unused_buffer(QEMUFile *f, void *pv, size_t size, static int put_unused_buffer(QEMUFile *f, void *pv, size_t size,
const VMStateField *field, QJSON *vmdesc) const VMStateField *field, JSONWriter *vmdesc)
{ {
static const uint8_t buf[1024]; static const uint8_t buf[1024];
int block_len; int block_len;
@ -530,7 +530,7 @@ static int get_tmp(QEMUFile *f, void *pv, size_t size,
} }
static int put_tmp(QEMUFile *f, void *pv, size_t size, static int put_tmp(QEMUFile *f, void *pv, size_t size,
const VMStateField *field, QJSON *vmdesc) const VMStateField *field, JSONWriter *vmdesc)
{ {
const VMStateDescription *vmsd = field->vmsd; const VMStateDescription *vmsd = field->vmsd;
void *tmp = g_malloc(size); void *tmp = g_malloc(size);
@ -573,7 +573,7 @@ static int get_bitmap(QEMUFile *f, void *pv, size_t size,
} }
static int put_bitmap(QEMUFile *f, void *pv, size_t size, static int put_bitmap(QEMUFile *f, void *pv, size_t size,
const VMStateField *field, QJSON *vmdesc) const VMStateField *field, JSONWriter *vmdesc)
{ {
unsigned long *bmp = pv; unsigned long *bmp = pv;
int i, idx = 0; int i, idx = 0;
@ -637,7 +637,7 @@ static int get_qtailq(QEMUFile *f, void *pv, size_t unused_size,
/* put for QTAILQ */ /* put for QTAILQ */
static int put_qtailq(QEMUFile *f, void *pv, size_t unused_size, static int put_qtailq(QEMUFile *f, void *pv, size_t unused_size,
const VMStateField *field, QJSON *vmdesc) const VMStateField *field, JSONWriter *vmdesc)
{ {
const VMStateDescription *vmsd = field->vmsd; const VMStateDescription *vmsd = field->vmsd;
/* offset of the QTAILQ entry in a QTAILQ element*/ /* offset of the QTAILQ entry in a QTAILQ element*/
@ -670,7 +670,7 @@ struct put_gtree_data {
QEMUFile *f; QEMUFile *f;
const VMStateDescription *key_vmsd; const VMStateDescription *key_vmsd;
const VMStateDescription *val_vmsd; const VMStateDescription *val_vmsd;
QJSON *vmdesc; JSONWriter *vmdesc;
int ret; int ret;
}; };
@ -703,7 +703,7 @@ static gboolean put_gtree_elem(gpointer key, gpointer value, gpointer data)
} }
static int put_gtree(QEMUFile *f, void *pv, size_t unused_size, static int put_gtree(QEMUFile *f, void *pv, size_t unused_size,
const VMStateField *field, QJSON *vmdesc) const VMStateField *field, JSONWriter *vmdesc)
{ {
bool direct_key = (!field->start); bool direct_key = (!field->start);
const VMStateDescription *key_vmsd = direct_key ? NULL : &field->vmsd[1]; const VMStateDescription *key_vmsd = direct_key ? NULL : &field->vmsd[1];
@ -819,7 +819,7 @@ const VMStateInfo vmstate_info_gtree = {
}; };
static int put_qlist(QEMUFile *f, void *pv, size_t unused_size, static int put_qlist(QEMUFile *f, void *pv, size_t unused_size,
const VMStateField *field, QJSON *vmdesc) const VMStateField *field, JSONWriter *vmdesc)
{ {
const VMStateDescription *vmsd = field->vmsd; const VMStateDescription *vmsd = field->vmsd;
/* offset of the QTAILQ entry in a QTAILQ element*/ /* offset of the QTAILQ entry in a QTAILQ element*/

View File

@ -14,14 +14,14 @@
#include "migration.h" #include "migration.h"
#include "migration/vmstate.h" #include "migration/vmstate.h"
#include "savevm.h" #include "savevm.h"
#include "qapi/qmp/json-writer.h"
#include "qemu-file.h" #include "qemu-file.h"
#include "qemu/bitops.h" #include "qemu/bitops.h"
#include "qemu/error-report.h" #include "qemu/error-report.h"
#include "trace.h" #include "trace.h"
#include "qjson.h"
static int vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd, static int vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
void *opaque, QJSON *vmdesc); void *opaque, JSONWriter *vmdesc);
static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd, static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd,
void *opaque); void *opaque);
@ -249,7 +249,8 @@ static bool vmsd_can_compress(const VMStateField *field)
return true; return true;
} }
static void vmsd_desc_field_start(const VMStateDescription *vmsd, QJSON *vmdesc, static void vmsd_desc_field_start(const VMStateDescription *vmsd,
JSONWriter *vmdesc,
const VMStateField *field, int i, int max) const VMStateField *field, int i, int max)
{ {
char *name, *old_name; char *name, *old_name;
@ -270,25 +271,26 @@ static void vmsd_desc_field_start(const VMStateDescription *vmsd, QJSON *vmdesc,
g_free(old_name); g_free(old_name);
} }
json_start_object(vmdesc, NULL); json_writer_start_object(vmdesc, NULL);
json_prop_str(vmdesc, "name", name); json_writer_str(vmdesc, "name", name);
if (is_array) { if (is_array) {
if (can_compress) { if (can_compress) {
json_prop_int(vmdesc, "array_len", max); json_writer_int64(vmdesc, "array_len", max);
} else { } else {
json_prop_int(vmdesc, "index", i); json_writer_int64(vmdesc, "index", i);
} }
} }
json_prop_str(vmdesc, "type", vmfield_get_type_name(field)); json_writer_str(vmdesc, "type", vmfield_get_type_name(field));
if (field->flags & VMS_STRUCT) { if (field->flags & VMS_STRUCT) {
json_start_object(vmdesc, "struct"); json_writer_start_object(vmdesc, "struct");
} }
g_free(name); g_free(name);
} }
static void vmsd_desc_field_end(const VMStateDescription *vmsd, QJSON *vmdesc, static void vmsd_desc_field_end(const VMStateDescription *vmsd,
JSONWriter *vmdesc,
const VMStateField *field, size_t size, int i) const VMStateField *field, size_t size, int i)
{ {
if (!vmdesc) { if (!vmdesc) {
@ -297,11 +299,11 @@ static void vmsd_desc_field_end(const VMStateDescription *vmsd, QJSON *vmdesc,
if (field->flags & VMS_STRUCT) { if (field->flags & VMS_STRUCT) {
/* We printed a struct in between, close its child object */ /* We printed a struct in between, close its child object */
json_end_object(vmdesc); json_writer_end_object(vmdesc);
} }
json_prop_int(vmdesc, "size", size); json_writer_int64(vmdesc, "size", size);
json_end_object(vmdesc); json_writer_end_object(vmdesc);
} }
@ -316,13 +318,13 @@ bool vmstate_save_needed(const VMStateDescription *vmsd, void *opaque)
int vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd, int vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
void *opaque, QJSON *vmdesc_id) void *opaque, JSONWriter *vmdesc_id)
{ {
return vmstate_save_state_v(f, vmsd, opaque, vmdesc_id, vmsd->version_id); return vmstate_save_state_v(f, vmsd, opaque, vmdesc_id, vmsd->version_id);
} }
int vmstate_save_state_v(QEMUFile *f, const VMStateDescription *vmsd, int vmstate_save_state_v(QEMUFile *f, const VMStateDescription *vmsd,
void *opaque, QJSON *vmdesc, int version_id) void *opaque, JSONWriter *vmdesc, int version_id)
{ {
int ret = 0; int ret = 0;
const VMStateField *field = vmsd->fields; const VMStateField *field = vmsd->fields;
@ -339,9 +341,9 @@ int vmstate_save_state_v(QEMUFile *f, const VMStateDescription *vmsd,
} }
if (vmdesc) { if (vmdesc) {
json_prop_str(vmdesc, "vmsd_name", vmsd->name); json_writer_str(vmdesc, "vmsd_name", vmsd->name);
json_prop_int(vmdesc, "version", version_id); json_writer_int64(vmdesc, "version", version_id);
json_start_array(vmdesc, "fields"); json_writer_start_array(vmdesc, "fields");
} }
while (field->name) { while (field->name) {
@ -353,7 +355,7 @@ int vmstate_save_state_v(QEMUFile *f, const VMStateDescription *vmsd,
int i, n_elems = vmstate_n_elems(opaque, field); int i, n_elems = vmstate_n_elems(opaque, field);
int size = vmstate_size(opaque, field); int size = vmstate_size(opaque, field);
int64_t old_offset, written_bytes; int64_t old_offset, written_bytes;
QJSON *vmdesc_loop = vmdesc; JSONWriter *vmdesc_loop = vmdesc;
trace_vmstate_save_state_loop(vmsd->name, field->name, n_elems); trace_vmstate_save_state_loop(vmsd->name, field->name, n_elems);
if (field->flags & VMS_POINTER) { if (field->flags & VMS_POINTER) {
@ -413,7 +415,7 @@ int vmstate_save_state_v(QEMUFile *f, const VMStateDescription *vmsd,
} }
if (vmdesc) { if (vmdesc) {
json_end_array(vmdesc); json_writer_end_array(vmdesc);
} }
ret = vmstate_subsection_save(f, vmsd, opaque, vmdesc); ret = vmstate_subsection_save(f, vmsd, opaque, vmdesc);
@ -491,7 +493,7 @@ static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd,
} }
static int vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd, static int vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
void *opaque, QJSON *vmdesc) void *opaque, JSONWriter *vmdesc)
{ {
const VMStateDescription **sub = vmsd->subsections; const VMStateDescription **sub = vmsd->subsections;
bool vmdesc_has_subsections = false; bool vmdesc_has_subsections = false;
@ -507,11 +509,11 @@ static int vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
if (vmdesc) { if (vmdesc) {
/* Only create subsection array when we have any */ /* Only create subsection array when we have any */
if (!vmdesc_has_subsections) { if (!vmdesc_has_subsections) {
json_start_array(vmdesc, "subsections"); json_writer_start_array(vmdesc, "subsections");
vmdesc_has_subsections = true; vmdesc_has_subsections = true;
} }
json_start_object(vmdesc, NULL); json_writer_start_object(vmdesc, NULL);
} }
qemu_put_byte(f, QEMU_VM_SUBSECTION); qemu_put_byte(f, QEMU_VM_SUBSECTION);
@ -525,14 +527,14 @@ static int vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
} }
if (vmdesc) { if (vmdesc) {
json_end_object(vmdesc); json_writer_end_object(vmdesc);
} }
} }
sub++; sub++;
} }
if (vmdesc_has_subsections) { if (vmdesc_has_subsections) {
json_end_array(vmdesc); json_writer_end_array(vmdesc);
} }
return ret; return ret;

View File

@ -1255,7 +1255,8 @@ void hmp_migrate_set_capability(Monitor *mon, const QDict *qdict)
const char *cap = qdict_get_str(qdict, "capability"); const char *cap = qdict_get_str(qdict, "capability");
bool state = qdict_get_bool(qdict, "state"); bool state = qdict_get_bool(qdict, "state");
Error *err = NULL; Error *err = NULL;
MigrationCapabilityStatusList *caps = g_malloc0(sizeof(*caps)); MigrationCapabilityStatusList *caps = NULL;
MigrationCapabilityStatus *value;
int val; int val;
val = qapi_enum_parse(&MigrationCapability_lookup, cap, -1, &err); val = qapi_enum_parse(&MigrationCapability_lookup, cap, -1, &err);
@ -1263,14 +1264,14 @@ void hmp_migrate_set_capability(Monitor *mon, const QDict *qdict)
goto end; goto end;
} }
caps->value = g_malloc0(sizeof(*caps->value)); value = g_malloc0(sizeof(*value));
caps->value->capability = val; value->capability = val;
caps->value->state = state; value->state = state;
caps->next = NULL; QAPI_LIST_PREPEND(caps, value);
qmp_migrate_set_capabilities(caps, &err); qmp_migrate_set_capabilities(caps, &err);
qapi_free_MigrationCapabilityStatusList(caps);
end: end:
qapi_free_MigrationCapabilityStatusList(caps);
hmp_handle_error(mon, err); hmp_handle_error(mon, err);
} }

View File

@ -136,11 +136,7 @@ char *qmp_human_monitor_command(const char *command_line, bool has_cpu_index,
handle_hmp_command(&hmp, command_line); handle_hmp_command(&hmp, command_line);
WITH_QEMU_LOCK_GUARD(&hmp.common.mon_lock) { WITH_QEMU_LOCK_GUARD(&hmp.common.mon_lock) {
if (qstring_get_length(hmp.common.outbuf) > 0) { output = g_strdup(hmp.common.outbuf->str);
output = g_strdup(qstring_get_str(hmp.common.outbuf));
} else {
output = g_strdup("");
}
} }
out: out:
@ -1434,33 +1430,26 @@ FdsetInfoList *qmp_query_fdsets(Error **errp)
QEMU_LOCK_GUARD(&mon_fdsets_lock); QEMU_LOCK_GUARD(&mon_fdsets_lock);
QLIST_FOREACH(mon_fdset, &mon_fdsets, next) { QLIST_FOREACH(mon_fdset, &mon_fdsets, next) {
FdsetInfoList *fdset_info = g_malloc0(sizeof(*fdset_info)); FdsetInfo *fdset_info = g_malloc0(sizeof(*fdset_info));
FdsetFdInfoList *fdsetfd_list = NULL;
fdset_info->value = g_malloc0(sizeof(*fdset_info->value)); fdset_info->fdset_id = mon_fdset->id;
fdset_info->value->fdset_id = mon_fdset->id;
QLIST_FOREACH(mon_fdset_fd, &mon_fdset->fds, next) { QLIST_FOREACH(mon_fdset_fd, &mon_fdset->fds, next) {
FdsetFdInfoList *fdsetfd_info; FdsetFdInfo *fdsetfd_info;
fdsetfd_info = g_malloc0(sizeof(*fdsetfd_info)); fdsetfd_info = g_malloc0(sizeof(*fdsetfd_info));
fdsetfd_info->value = g_malloc0(sizeof(*fdsetfd_info->value)); fdsetfd_info->fd = mon_fdset_fd->fd;
fdsetfd_info->value->fd = mon_fdset_fd->fd;
if (mon_fdset_fd->opaque) { if (mon_fdset_fd->opaque) {
fdsetfd_info->value->has_opaque = true; fdsetfd_info->has_opaque = true;
fdsetfd_info->value->opaque = g_strdup(mon_fdset_fd->opaque); fdsetfd_info->opaque = g_strdup(mon_fdset_fd->opaque);
} else { } else {
fdsetfd_info->value->has_opaque = false; fdsetfd_info->has_opaque = false;
} }
fdsetfd_info->next = fdsetfd_list; QAPI_LIST_PREPEND(fdset_info->fds, fdsetfd_info);
fdsetfd_list = fdsetfd_info;
} }
fdset_info->value->fds = fdsetfd_list; QAPI_LIST_PREPEND(fdset_list, fdset_info);
fdset_info->next = fdset_list;
fdset_list = fdset_info;
} }
return fdset_list; return fdset_list;

View File

@ -105,7 +105,7 @@ struct Monitor {
* Members that are protected by the per-monitor lock * Members that are protected by the per-monitor lock
*/ */
QLIST_HEAD(, mon_fd_t) fds; QLIST_HEAD(, mon_fd_t) fds;
QString *outbuf; GString *outbuf;
guint out_watch; guint out_watch;
/* Read under either BQL or mon_lock, written with BQL+mon_lock. */ /* Read under either BQL or mon_lock, written with BQL+mon_lock. */
int mux_out; int mux_out;

View File

@ -29,7 +29,6 @@
#include "qapi/qapi-emit-events.h" #include "qapi/qapi-emit-events.h"
#include "qapi/qapi-visit-control.h" #include "qapi/qapi-visit-control.h"
#include "qapi/qmp/qdict.h" #include "qapi/qmp/qdict.h"
#include "qapi/qmp/qstring.h"
#include "qemu/error-report.h" #include "qemu/error-report.h"
#include "qemu/option.h" #include "qemu/option.h"
#include "sysemu/qtest.h" #include "sysemu/qtest.h"
@ -181,22 +180,19 @@ static void monitor_flush_locked(Monitor *mon)
return; return;
} }
buf = qstring_get_str(mon->outbuf); buf = mon->outbuf->str;
len = qstring_get_length(mon->outbuf); len = mon->outbuf->len;
if (len && !mon->mux_out) { if (len && !mon->mux_out) {
rc = qemu_chr_fe_write(&mon->chr, (const uint8_t *) buf, len); rc = qemu_chr_fe_write(&mon->chr, (const uint8_t *) buf, len);
if ((rc < 0 && errno != EAGAIN) || (rc == len)) { if ((rc < 0 && errno != EAGAIN) || (rc == len)) {
/* all flushed or error */ /* all flushed or error */
qobject_unref(mon->outbuf); g_string_truncate(mon->outbuf, 0);
mon->outbuf = qstring_new();
return; return;
} }
if (rc > 0) { if (rc > 0) {
/* partial write */ /* partial write */
QString *tmp = qstring_from_str(buf + rc); g_string_erase(mon->outbuf, 0, rc);
qobject_unref(mon->outbuf);
mon->outbuf = tmp;
} }
if (mon->out_watch == 0) { if (mon->out_watch == 0) {
mon->out_watch = mon->out_watch =
@ -223,9 +219,9 @@ int monitor_puts(Monitor *mon, const char *str)
for (i = 0; str[i]; i++) { for (i = 0; str[i]; i++) {
c = str[i]; c = str[i];
if (c == '\n') { if (c == '\n') {
qstring_append_chr(mon->outbuf, '\r'); g_string_append_c(mon->outbuf, '\r');
} }
qstring_append_chr(mon->outbuf, c); g_string_append_c(mon->outbuf, c);
if (c == '\n') { if (c == '\n') {
monitor_flush_locked(mon); monitor_flush_locked(mon);
} }
@ -602,7 +598,7 @@ void monitor_data_init(Monitor *mon, bool is_qmp, bool skip_flush,
} }
qemu_mutex_init(&mon->mon_lock); qemu_mutex_init(&mon->mon_lock);
mon->is_qmp = is_qmp; mon->is_qmp = is_qmp;
mon->outbuf = qstring_new(); mon->outbuf = g_string_new(NULL);
mon->skip_flush = skip_flush; mon->skip_flush = skip_flush;
mon->use_io_thread = use_io_thread; mon->use_io_thread = use_io_thread;
} }
@ -616,7 +612,7 @@ void monitor_data_destroy(Monitor *mon)
} else { } else {
readline_free(container_of(mon, MonitorHMP, common)->rs); readline_free(container_of(mon, MonitorHMP, common)->rs);
} }
qobject_unref(mon->outbuf); g_string_free(mon->outbuf, true);
qemu_mutex_destroy(&mon->mon_lock); qemu_mutex_destroy(&mon->mon_lock);
} }

View File

@ -138,18 +138,18 @@ EventInfoList *qmp_query_events(Error **errp)
* QAPIEvent_str() and QAPIEvent_lookup[]. When the command goes, * QAPIEvent_str() and QAPIEvent_lookup[]. When the command goes,
* they should go, too. * they should go, too.
*/ */
EventInfoList *info, *ev_list = NULL; EventInfoList *ev_list = NULL;
QAPIEvent e; QAPIEvent e;
for (e = 0 ; e < QAPI_EVENT__MAX ; e++) { for (e = 0 ; e < QAPI_EVENT__MAX ; e++) {
const char *event_name = QAPIEvent_str(e); const char *event_name = QAPIEvent_str(e);
EventInfo *info;
assert(event_name != NULL); assert(event_name != NULL);
info = g_malloc0(sizeof(*info)); info = g_malloc0(sizeof(*info));
info->value = g_malloc0(sizeof(*info->value)); info->name = g_strdup(event_name);
info->value->name = g_strdup(event_name);
info->next = ev_list; QAPI_LIST_PREPEND(ev_list, info);
ev_list = info;
} }
return ev_list; return ev_list;

View File

@ -31,7 +31,6 @@
#include "qapi/qmp/qdict.h" #include "qapi/qmp/qdict.h"
#include "qapi/qmp/qjson.h" #include "qapi/qmp/qjson.h"
#include "qapi/qmp/qlist.h" #include "qapi/qmp/qlist.h"
#include "qapi/qmp/qstring.h"
#include "trace.h" #include "trace.h"
struct QMPRequest { struct QMPRequest {
@ -110,15 +109,15 @@ static void monitor_qmp_cleanup_queue_and_resume(MonitorQMP *mon)
void qmp_send_response(MonitorQMP *mon, const QDict *rsp) void qmp_send_response(MonitorQMP *mon, const QDict *rsp)
{ {
const QObject *data = QOBJECT(rsp); const QObject *data = QOBJECT(rsp);
QString *json; GString *json;
json = mon->pretty ? qobject_to_json_pretty(data) : qobject_to_json(data); json = qobject_to_json_pretty(data, mon->pretty);
assert(json != NULL); assert(json != NULL);
qstring_append_chr(json, '\n'); g_string_append_c(json, '\n');
monitor_puts(&mon->common, qstring_get_str(json)); monitor_puts(&mon->common, json->str);
qobject_unref(json); g_string_free(json, true);
} }
/* /*
@ -276,9 +275,15 @@ void coroutine_fn monitor_qmp_dispatcher_co(void *data)
mon->qmp_requests->length == QMP_REQ_QUEUE_LEN_MAX - 1; mon->qmp_requests->length == QMP_REQ_QUEUE_LEN_MAX - 1;
qemu_mutex_unlock(&mon->qmp_queue_lock); qemu_mutex_unlock(&mon->qmp_queue_lock);
if (req_obj->req) { if (req_obj->req) {
QDict *qdict = qobject_to(QDict, req_obj->req); if (trace_event_get_state(TRACE_MONITOR_QMP_CMD_IN_BAND)) {
QObject *id = qdict ? qdict_get(qdict, "id") : NULL; QDict *qdict = qobject_to(QDict, req_obj->req);
trace_monitor_qmp_cmd_in_band(qobject_get_try_str(id) ?: ""); QObject *id = qdict ? qdict_get(qdict, "id") : NULL;
GString *id_json;
id_json = id ? qobject_to_json(id) : g_string_new(NULL);
trace_monitor_qmp_cmd_in_band(id_json->str);
g_string_free(id_json, true);
}
monitor_qmp_dispatch(mon, req_obj->req); monitor_qmp_dispatch(mon, req_obj->req);
} else { } else {
assert(req_obj->err); assert(req_obj->err);
@ -308,26 +313,27 @@ void coroutine_fn monitor_qmp_dispatcher_co(void *data)
static void handle_qmp_command(void *opaque, QObject *req, Error *err) static void handle_qmp_command(void *opaque, QObject *req, Error *err)
{ {
MonitorQMP *mon = opaque; MonitorQMP *mon = opaque;
QObject *id = NULL; QDict *qdict = qobject_to(QDict, req);
QDict *qdict;
QMPRequest *req_obj; QMPRequest *req_obj;
assert(!req != !err); assert(!req != !err);
qdict = qobject_to(QDict, req);
if (qdict) {
id = qdict_get(qdict, "id");
} /* else will fail qmp_dispatch() */
if (req && trace_event_get_state_backends(TRACE_HANDLE_QMP_COMMAND)) { if (req && trace_event_get_state_backends(TRACE_HANDLE_QMP_COMMAND)) {
QString *req_json = qobject_to_json(req); GString *req_json = qobject_to_json(req);
trace_handle_qmp_command(mon, qstring_get_str(req_json)); trace_handle_qmp_command(mon, req_json->str);
qobject_unref(req_json); g_string_free(req_json, true);
} }
if (qdict && qmp_is_oob(qdict)) { if (qdict && qmp_is_oob(qdict)) {
/* OOB commands are executed immediately */ /* OOB commands are executed immediately */
trace_monitor_qmp_cmd_out_of_band(qobject_get_try_str(id) ?: ""); if (trace_event_get_state(TRACE_MONITOR_QMP_CMD_OUT_OF_BAND)) {
QObject *id = qdict_get(qdict, "id");
GString *id_json;
id_json = id ? qobject_to_json(id) : g_string_new(NULL);
trace_monitor_qmp_cmd_out_of_band(id_json->str);
g_string_free(id_json, true);
}
monitor_qmp_dispatch(mon, req); monitor_qmp_dispatch(mon, req);
qobject_unref(req); qobject_unref(req);
return; return;

View File

@ -258,7 +258,7 @@ static bool print_type_number(Visitor *v, const char *name, double *obj,
Error **errp) Error **errp)
{ {
StringOutputVisitor *sov = to_sov(v); StringOutputVisitor *sov = to_sov(v);
string_output_set(sov, g_strdup_printf("%f", *obj)); string_output_set(sov, g_strdup_printf("%.17g", *obj));
return true; return true;
} }

View File

@ -33,7 +33,6 @@
#include "qapi/qobject-output-visitor.h" #include "qapi/qobject-output-visitor.h"
#include "qapi/qmp/qjson.h" #include "qapi/qmp/qjson.h"
#include "qapi/qmp/qdict.h" #include "qapi/qmp/qdict.h"
#include "qapi/qmp/qstring.h"
#include "qemu/cutils.h" #include "qemu/cutils.h"
#include "qemu/config-file.h" #include "qemu/config-file.h"
#include "qemu/option.h" #include "qemu/option.h"
@ -627,18 +626,18 @@ fail:
static void dump_json_image_check(ImageCheck *check, bool quiet) static void dump_json_image_check(ImageCheck *check, bool quiet)
{ {
QString *str; GString *str;
QObject *obj; QObject *obj;
Visitor *v = qobject_output_visitor_new(&obj); Visitor *v = qobject_output_visitor_new(&obj);
visit_type_ImageCheck(v, NULL, &check, &error_abort); visit_type_ImageCheck(v, NULL, &check, &error_abort);
visit_complete(v, &obj); visit_complete(v, &obj);
str = qobject_to_json_pretty(obj); str = qobject_to_json_pretty(obj, true);
assert(str != NULL); assert(str != NULL);
qprintf(quiet, "%s\n", qstring_get_str(str)); qprintf(quiet, "%s\n", str->str);
qobject_unref(obj); qobject_unref(obj);
visit_free(v); visit_free(v);
qobject_unref(str); g_string_free(str, true);
} }
static void dump_human_image_check(ImageCheck *check, bool quiet) static void dump_human_image_check(ImageCheck *check, bool quiet)
@ -1652,14 +1651,13 @@ static void do_dirty_bitmap_merge(const char *dst_node, const char *dst_name,
Error **errp) Error **errp)
{ {
BlockDirtyBitmapMergeSource *merge_src; BlockDirtyBitmapMergeSource *merge_src;
BlockDirtyBitmapMergeSourceList *list; BlockDirtyBitmapMergeSourceList *list = NULL;
merge_src = g_new0(BlockDirtyBitmapMergeSource, 1); merge_src = g_new0(BlockDirtyBitmapMergeSource, 1);
merge_src->type = QTYPE_QDICT; merge_src->type = QTYPE_QDICT;
merge_src->u.external.node = g_strdup(src_node); merge_src->u.external.node = g_strdup(src_node);
merge_src->u.external.name = g_strdup(src_name); merge_src->u.external.name = g_strdup(src_name);
list = g_new0(BlockDirtyBitmapMergeSourceList, 1); QAPI_LIST_PREPEND(list, merge_src);
list->value = merge_src;
qmp_block_dirty_bitmap_merge(dst_node, dst_name, list, errp); qmp_block_dirty_bitmap_merge(dst_node, dst_name, list, errp);
qapi_free_BlockDirtyBitmapMergeSourceList(list); qapi_free_BlockDirtyBitmapMergeSourceList(list);
} }
@ -2790,34 +2788,34 @@ static void dump_snapshots(BlockDriverState *bs)
static void dump_json_image_info_list(ImageInfoList *list) static void dump_json_image_info_list(ImageInfoList *list)
{ {
QString *str; GString *str;
QObject *obj; QObject *obj;
Visitor *v = qobject_output_visitor_new(&obj); Visitor *v = qobject_output_visitor_new(&obj);
visit_type_ImageInfoList(v, NULL, &list, &error_abort); visit_type_ImageInfoList(v, NULL, &list, &error_abort);
visit_complete(v, &obj); visit_complete(v, &obj);
str = qobject_to_json_pretty(obj); str = qobject_to_json_pretty(obj, true);
assert(str != NULL); assert(str != NULL);
printf("%s\n", qstring_get_str(str)); printf("%s\n", str->str);
qobject_unref(obj); qobject_unref(obj);
visit_free(v); visit_free(v);
qobject_unref(str); g_string_free(str, true);
} }
static void dump_json_image_info(ImageInfo *info) static void dump_json_image_info(ImageInfo *info)
{ {
QString *str; GString *str;
QObject *obj; QObject *obj;
Visitor *v = qobject_output_visitor_new(&obj); Visitor *v = qobject_output_visitor_new(&obj);
visit_type_ImageInfo(v, NULL, &info, &error_abort); visit_type_ImageInfo(v, NULL, &info, &error_abort);
visit_complete(v, &obj); visit_complete(v, &obj);
str = qobject_to_json_pretty(obj); str = qobject_to_json_pretty(obj, true);
assert(str != NULL); assert(str != NULL);
printf("%s\n", qstring_get_str(str)); printf("%s\n", str->str);
qobject_unref(obj); qobject_unref(obj);
visit_free(v); visit_free(v);
qobject_unref(str); g_string_free(str, true);
} }
static void dump_human_image_info_list(ImageInfoList *list) static void dump_human_image_info_list(ImageInfoList *list)
@ -5237,18 +5235,18 @@ out:
static void dump_json_block_measure_info(BlockMeasureInfo *info) static void dump_json_block_measure_info(BlockMeasureInfo *info)
{ {
QString *str; GString *str;
QObject *obj; QObject *obj;
Visitor *v = qobject_output_visitor_new(&obj); Visitor *v = qobject_output_visitor_new(&obj);
visit_type_BlockMeasureInfo(v, NULL, &info, &error_abort); visit_type_BlockMeasureInfo(v, NULL, &info, &error_abort);
visit_complete(v, &obj); visit_complete(v, &obj);
str = qobject_to_json_pretty(obj); str = qobject_to_json_pretty(obj, true);
assert(str != NULL); assert(str != NULL);
printf("%s\n", qstring_get_str(str)); printf("%s\n", str->str);
qobject_unref(obj); qobject_unref(obj);
visit_free(v); visit_free(v);
qobject_unref(str); g_string_free(str, true);
} }
static int img_measure(int argc, char **argv) static int img_measure(int argc, char **argv)

View File

@ -293,17 +293,12 @@ qmp_guest_ssh_get_authorized_keys(const char *username, Error **errp)
ret = g_new0(GuestAuthorizedKeys, 1); ret = g_new0(GuestAuthorizedKeys, 1);
for (i = 0; authkeys[i] != NULL; i++) { for (i = 0; authkeys[i] != NULL; i++) {
strList *new;
g_strstrip(authkeys[i]); g_strstrip(authkeys[i]);
if (!authkeys[i][0] || authkeys[i][0] == '#') { if (!authkeys[i][0] || authkeys[i][0] == '#') {
continue; continue;
} }
new = g_new0(strList, 1); QAPI_LIST_PREPEND(ret->keys, g_strdup(authkeys[i]));
new->value = g_strdup(authkeys[i]);
new->next = ret->keys;
ret->keys = new;
} }
return g_steal_pointer(&ret); return g_steal_pointer(&ret);

View File

@ -1036,7 +1036,6 @@ static void build_guest_fsinfo_for_real_device(char const *syspath,
{ {
GuestDiskAddress *disk; GuestDiskAddress *disk;
GuestPCIAddress *pciaddr; GuestPCIAddress *pciaddr;
GuestDiskAddressList *list = NULL;
bool has_hwinf; bool has_hwinf;
#ifdef CONFIG_LIBUDEV #ifdef CONFIG_LIBUDEV
struct udev *udev = NULL; struct udev *udev = NULL;
@ -1053,9 +1052,6 @@ static void build_guest_fsinfo_for_real_device(char const *syspath,
disk->pci_controller = pciaddr; disk->pci_controller = pciaddr;
disk->bus_type = GUEST_DISK_BUS_TYPE_UNKNOWN; disk->bus_type = GUEST_DISK_BUS_TYPE_UNKNOWN;
list = g_new0(GuestDiskAddressList, 1);
list->value = disk;
#ifdef CONFIG_LIBUDEV #ifdef CONFIG_LIBUDEV
udev = udev_new(); udev = udev_new();
udevice = udev_device_new_from_syspath(udev, syspath); udevice = udev_device_new_from_syspath(udev, syspath);
@ -1089,10 +1085,9 @@ static void build_guest_fsinfo_for_real_device(char const *syspath,
} }
if (has_hwinf || disk->has_dev || disk->has_serial) { if (has_hwinf || disk->has_dev || disk->has_serial) {
list->next = fs->disk; QAPI_LIST_PREPEND(fs->disk, disk);
fs->disk = list;
} else { } else {
qapi_free_GuestDiskAddressList(list); qapi_free_GuestDiskAddress(disk);
} }
} }
@ -1288,7 +1283,6 @@ static void get_disk_deps(const char *disk_dir, GuestDiskInfo *disk)
disk->has_dependencies = true; disk->has_dependencies = true;
while ((dep = g_dir_read_name(dp_deps)) != NULL) { while ((dep = g_dir_read_name(dp_deps)) != NULL) {
g_autofree char *dep_dir = NULL; g_autofree char *dep_dir = NULL;
strList *dep_item = NULL;
char *dev_name; char *dev_name;
/* Add dependent disks */ /* Add dependent disks */
@ -1296,10 +1290,7 @@ static void get_disk_deps(const char *disk_dir, GuestDiskInfo *disk)
dev_name = get_device_for_syspath(dep_dir); dev_name = get_device_for_syspath(dep_dir);
if (dev_name != NULL) { if (dev_name != NULL) {
g_debug(" adding dependent device: %s", dev_name); g_debug(" adding dependent device: %s", dev_name);
dep_item = g_new0(strList, 1); QAPI_LIST_PREPEND(disk->dependencies, dev_name);
dep_item->value = dev_name;
dep_item->next = disk->dependencies;
disk->dependencies = dep_item;
} }
} }
g_dir_close(dp_deps); g_dir_close(dp_deps);
@ -1318,7 +1309,7 @@ static GuestDiskInfoList *get_disk_partitions(
const char *disk_name, const char *disk_dir, const char *disk_name, const char *disk_dir,
const char *disk_dev) const char *disk_dev)
{ {
GuestDiskInfoList *item, *ret = list; GuestDiskInfoList *ret = list;
struct dirent *de_disk; struct dirent *de_disk;
DIR *dp_disk = NULL; DIR *dp_disk = NULL;
size_t len = strlen(disk_name); size_t len = strlen(disk_name);
@ -1352,15 +1343,9 @@ static GuestDiskInfoList *get_disk_partitions(
partition->name = dev_name; partition->name = dev_name;
partition->partition = true; partition->partition = true;
/* Add parent disk as dependent for easier tracking of hierarchy */ /* Add parent disk as dependent for easier tracking of hierarchy */
partition->dependencies = g_new0(strList, 1); QAPI_LIST_PREPEND(partition->dependencies, g_strdup(disk_dev));
partition->dependencies->value = g_strdup(disk_dev);
partition->has_dependencies = true;
item = g_new0(GuestDiskInfoList, 1);
item->value = partition;
item->next = ret;
ret = item;
QAPI_LIST_PREPEND(ret, partition);
} }
closedir(dp_disk); closedir(dp_disk);
@ -1369,7 +1354,7 @@ static GuestDiskInfoList *get_disk_partitions(
GuestDiskInfoList *qmp_guest_get_disks(Error **errp) GuestDiskInfoList *qmp_guest_get_disks(Error **errp)
{ {
GuestDiskInfoList *item, *ret = NULL; GuestDiskInfoList *ret = NULL;
GuestDiskInfo *disk; GuestDiskInfo *disk;
DIR *dp = NULL; DIR *dp = NULL;
struct dirent *de = NULL; struct dirent *de = NULL;
@ -1415,10 +1400,7 @@ GuestDiskInfoList *qmp_guest_get_disks(Error **errp)
disk->partition = false; disk->partition = false;
disk->alias = get_alias_for_syspath(disk_dir); disk->alias = get_alias_for_syspath(disk_dir);
disk->has_alias = (disk->alias != NULL); disk->has_alias = (disk->alias != NULL);
item = g_new0(GuestDiskInfoList, 1); QAPI_LIST_PREPEND(ret, disk);
item->value = disk;
item->next = ret;
ret = item;
/* Get address for non-virtual devices */ /* Get address for non-virtual devices */
bool is_virtual = is_disk_virtual(disk_dir, &local_err); bool is_virtual = is_disk_virtual(disk_dir, &local_err);
@ -1495,7 +1477,7 @@ GuestFilesystemInfoList *qmp_guest_get_fsinfo(Error **errp)
{ {
FsMountList mounts; FsMountList mounts;
struct FsMount *mount; struct FsMount *mount;
GuestFilesystemInfoList *new, *ret = NULL; GuestFilesystemInfoList *ret = NULL;
Error *local_err = NULL; Error *local_err = NULL;
QTAILQ_INIT(&mounts); QTAILQ_INIT(&mounts);
@ -1508,10 +1490,7 @@ GuestFilesystemInfoList *qmp_guest_get_fsinfo(Error **errp)
QTAILQ_FOREACH(mount, &mounts, next) { QTAILQ_FOREACH(mount, &mounts, next) {
g_debug("Building guest fsinfo for '%s'", mount->dirname); g_debug("Building guest fsinfo for '%s'", mount->dirname);
new = g_malloc0(sizeof(*ret)); QAPI_LIST_PREPEND(ret, build_guest_fsinfo(mount, &local_err));
new->value = build_guest_fsinfo(mount, &local_err);
new->next = ret;
ret = new;
if (local_err) { if (local_err) {
error_propagate(errp, local_err); error_propagate(errp, local_err);
qapi_free_GuestFilesystemInfoList(ret); qapi_free_GuestFilesystemInfoList(ret);
@ -1777,7 +1756,6 @@ GuestFilesystemTrimResponse *
qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **errp) qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **errp)
{ {
GuestFilesystemTrimResponse *response; GuestFilesystemTrimResponse *response;
GuestFilesystemTrimResultList *list;
GuestFilesystemTrimResult *result; GuestFilesystemTrimResult *result;
int ret = 0; int ret = 0;
FsMountList mounts; FsMountList mounts;
@ -1801,10 +1779,7 @@ qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **errp)
result = g_malloc0(sizeof(*result)); result = g_malloc0(sizeof(*result));
result->path = g_strdup(mount->dirname); result->path = g_strdup(mount->dirname);
list = g_malloc0(sizeof(*list)); QAPI_LIST_PREPEND(response->paths, result);
list->value = result;
list->next = response->paths;
response->paths = list;
fd = qemu_open_old(mount->dirname, O_RDONLY); fd = qemu_open_old(mount->dirname, O_RDONLY);
if (fd == -1) { if (fd == -1) {

View File

@ -874,7 +874,7 @@ err_close:
static GuestDiskAddressList *build_guest_disk_info(char *guid, Error **errp) static GuestDiskAddressList *build_guest_disk_info(char *guid, Error **errp)
{ {
Error *local_err = NULL; Error *local_err = NULL;
GuestDiskAddressList *list = NULL, *cur_item = NULL; GuestDiskAddressList *list = NULL;
GuestDiskAddress *disk = NULL; GuestDiskAddress *disk = NULL;
int i; int i;
HANDLE vol_h; HANDLE vol_h;
@ -926,10 +926,8 @@ static GuestDiskAddressList *build_guest_disk_info(char *guid, Error **errp)
error_free(local_err); error_free(local_err);
goto out; goto out;
} }
list = g_malloc0(sizeof(*list)); QAPI_LIST_PREPEND(list, disk);
list->value = disk;
disk = NULL; disk = NULL;
list->next = NULL;
goto out; goto out;
} else { } else {
error_setg_win32(errp, GetLastError(), error_setg_win32(errp, GetLastError(),
@ -960,11 +958,8 @@ static GuestDiskAddressList *build_guest_disk_info(char *guid, Error **errp)
error_propagate(errp, local_err); error_propagate(errp, local_err);
goto out; goto out;
} }
cur_item = g_malloc0(sizeof(*list)); QAPI_LIST_PREPEND(list, disk);
cur_item->value = disk;
disk = NULL; disk = NULL;
cur_item->next = list;
list = cur_item;
} }
@ -982,7 +977,7 @@ out:
GuestDiskInfoList *qmp_guest_get_disks(Error **errp) GuestDiskInfoList *qmp_guest_get_disks(Error **errp)
{ {
ERRP_GUARD(); ERRP_GUARD();
GuestDiskInfoList *new = NULL, *ret = NULL; GuestDiskInfoList *ret = NULL;
HDEVINFO dev_info; HDEVINFO dev_info;
SP_DEVICE_INTERFACE_DATA dev_iface_data; SP_DEVICE_INTERFACE_DATA dev_iface_data;
int i; int i;
@ -1064,10 +1059,7 @@ GuestDiskInfoList *qmp_guest_get_disks(Error **errp)
disk->has_address = true; disk->has_address = true;
} }
new = g_malloc0(sizeof(GuestDiskInfoList)); QAPI_LIST_PREPEND(ret, disk);
new->value = disk;
new->next = ret;
ret = new;
} }
SetupDiDestroyDeviceInfoList(dev_info); SetupDiDestroyDeviceInfoList(dev_info);
@ -1165,7 +1157,7 @@ free:
GuestFilesystemInfoList *qmp_guest_get_fsinfo(Error **errp) GuestFilesystemInfoList *qmp_guest_get_fsinfo(Error **errp)
{ {
HANDLE vol_h; HANDLE vol_h;
GuestFilesystemInfoList *new, *ret = NULL; GuestFilesystemInfoList *ret = NULL;
char guid[256]; char guid[256];
vol_h = FindFirstVolume(guid, sizeof(guid)); vol_h = FindFirstVolume(guid, sizeof(guid));
@ -1183,10 +1175,7 @@ GuestFilesystemInfoList *qmp_guest_get_fsinfo(Error **errp)
error_free(local_err); error_free(local_err);
continue; continue;
} }
new = g_malloc(sizeof(*ret)); QAPI_LIST_PREPEND(ret, info);
new->value = info;
new->next = ret;
ret = new;
} while (FindNextVolume(vol_h, guid, sizeof(guid))); } while (FindNextVolume(vol_h, guid, sizeof(guid)));
if (GetLastError() != ERROR_NO_MORE_FILES) { if (GetLastError() != ERROR_NO_MORE_FILES) {
@ -1330,7 +1319,6 @@ qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **errp)
do { do {
GuestFilesystemTrimResult *res; GuestFilesystemTrimResult *res;
GuestFilesystemTrimResultList *list;
PWCHAR uc_path; PWCHAR uc_path;
DWORD char_count = 0; DWORD char_count = 0;
char *path, *out; char *path, *out;
@ -1369,11 +1357,7 @@ qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **errp)
res->path = path; res->path = path;
list = g_new0(GuestFilesystemTrimResultList, 1); QAPI_LIST_PREPEND(resp->paths, res);
list->value = res;
list->next = resp->paths;
resp->paths = list;
memset(argv, 0, sizeof(argv)); memset(argv, 0, sizeof(argv));
argv[0] = (gchar *)"defrag.exe"; argv[0] = (gchar *)"defrag.exe";

View File

@ -66,17 +66,13 @@ static void qmp_command_info(const QmpCommand *cmd, void *opaque)
{ {
GuestAgentInfo *info = opaque; GuestAgentInfo *info = opaque;
GuestAgentCommandInfo *cmd_info; GuestAgentCommandInfo *cmd_info;
GuestAgentCommandInfoList *cmd_info_list;
cmd_info = g_new0(GuestAgentCommandInfo, 1); cmd_info = g_new0(GuestAgentCommandInfo, 1);
cmd_info->name = g_strdup(qmp_command_name(cmd)); cmd_info->name = g_strdup(qmp_command_name(cmd));
cmd_info->enabled = qmp_command_is_enabled(cmd); cmd_info->enabled = qmp_command_is_enabled(cmd);
cmd_info->success_response = qmp_has_success_response(cmd); cmd_info->success_response = qmp_has_success_response(cmd);
cmd_info_list = g_new0(GuestAgentCommandInfoList, 1); QAPI_LIST_PREPEND(info->supported_commands, cmd_info);
cmd_info_list->value = cmd_info;
cmd_info_list->next = info->supported_commands;
info->supported_commands = cmd_info_list;
} }
struct GuestAgentInfo *qmp_guest_info(Error **errp) struct GuestAgentInfo *qmp_guest_info(Error **errp)

View File

@ -22,7 +22,6 @@
#include "qapi/qmp/json-parser.h" #include "qapi/qmp/json-parser.h"
#include "qapi/qmp/qdict.h" #include "qapi/qmp/qdict.h"
#include "qapi/qmp/qjson.h" #include "qapi/qmp/qjson.h"
#include "qapi/qmp/qstring.h"
#include "guest-agent-core.h" #include "guest-agent-core.h"
#include "qga-qapi-init-commands.h" #include "qga-qapi-init-commands.h"
#include "qapi/qmp/qerror.h" #include "qapi/qmp/qerror.h"
@ -528,8 +527,7 @@ fail:
static int send_response(GAState *s, const QDict *rsp) static int send_response(GAState *s, const QDict *rsp)
{ {
const char *buf; GString *response;
QString *payload_qstr, *response_qstr;
GIOStatus status; GIOStatus status;
g_assert(s->channel); g_assert(s->channel);
@ -538,25 +536,19 @@ static int send_response(GAState *s, const QDict *rsp)
return 0; return 0;
} }
payload_qstr = qobject_to_json(QOBJECT(rsp)); response = qobject_to_json(QOBJECT(rsp));
if (!payload_qstr) { if (!response) {
return -EINVAL; return -EINVAL;
} }
if (s->delimit_response) { if (s->delimit_response) {
s->delimit_response = false; s->delimit_response = false;
response_qstr = qstring_new(); g_string_prepend_c(response, QGA_SENTINEL_BYTE);
qstring_append_chr(response_qstr, QGA_SENTINEL_BYTE);
qstring_append(response_qstr, qstring_get_str(payload_qstr));
qobject_unref(payload_qstr);
} else {
response_qstr = payload_qstr;
} }
qstring_append_chr(response_qstr, '\n'); g_string_append_c(response, '\n');
buf = qstring_get_str(response_qstr); status = ga_channel_write_all(s->channel, response->str, response->len);
status = ga_channel_write_all(s->channel, buf, strlen(buf)); g_string_free(response, true);
qobject_unref(response_qstr);
if (status != G_IO_STATUS_NORMAL) { if (status != G_IO_STATUS_NORMAL) {
return -EIO; return -EIO;
} }

View File

@ -130,7 +130,7 @@ static int cvt4hex(const char *s)
static QString *parse_string(JSONParserContext *ctxt, JSONToken *token) static QString *parse_string(JSONParserContext *ctxt, JSONToken *token)
{ {
const char *ptr = token->str; const char *ptr = token->str;
QString *str; GString *str;
char quote; char quote;
const char *beg; const char *beg;
int cp, trailing; int cp, trailing;
@ -140,7 +140,7 @@ static QString *parse_string(JSONParserContext *ctxt, JSONToken *token)
assert(*ptr == '"' || *ptr == '\''); assert(*ptr == '"' || *ptr == '\'');
quote = *ptr++; quote = *ptr++;
str = qstring_new(); str = g_string_new(NULL);
while (*ptr != quote) { while (*ptr != quote) {
assert(*ptr); assert(*ptr);
@ -149,31 +149,31 @@ static QString *parse_string(JSONParserContext *ctxt, JSONToken *token)
beg = ptr++; beg = ptr++;
switch (*ptr++) { switch (*ptr++) {
case '"': case '"':
qstring_append_chr(str, '"'); g_string_append_c(str, '"');
break; break;
case '\'': case '\'':
qstring_append_chr(str, '\''); g_string_append_c(str, '\'');
break; break;
case '\\': case '\\':
qstring_append_chr(str, '\\'); g_string_append_c(str, '\\');
break; break;
case '/': case '/':
qstring_append_chr(str, '/'); g_string_append_c(str, '/');
break; break;
case 'b': case 'b':
qstring_append_chr(str, '\b'); g_string_append_c(str, '\b');
break; break;
case 'f': case 'f':
qstring_append_chr(str, '\f'); g_string_append_c(str, '\f');
break; break;
case 'n': case 'n':
qstring_append_chr(str, '\n'); g_string_append_c(str, '\n');
break; break;
case 'r': case 'r':
qstring_append_chr(str, '\r'); g_string_append_c(str, '\r');
break; break;
case 't': case 't':
qstring_append_chr(str, '\t'); g_string_append_c(str, '\t');
break; break;
case 'u': case 'u':
cp = cvt4hex(ptr); cp = cvt4hex(ptr);
@ -200,7 +200,7 @@ static QString *parse_string(JSONParserContext *ctxt, JSONToken *token)
(int)(ptr - beg), beg); (int)(ptr - beg), beg);
goto out; goto out;
} }
qstring_append(str, utf8_buf); g_string_append(str, utf8_buf);
break; break;
default: default:
parse_error(ctxt, token, "invalid escape sequence in string"); parse_error(ctxt, token, "invalid escape sequence in string");
@ -225,14 +225,14 @@ static QString *parse_string(JSONParserContext *ctxt, JSONToken *token)
ptr = end; ptr = end;
len = mod_utf8_encode(utf8_buf, sizeof(utf8_buf), cp); len = mod_utf8_encode(utf8_buf, sizeof(utf8_buf), cp);
assert(len >= 0); assert(len >= 0);
qstring_append(str, utf8_buf); g_string_append(str, utf8_buf);
} }
} }
return str; return qstring_from_gstring(str);
out: out:
qobject_unref(str); g_string_free(str, true);
return NULL; return NULL;
} }

247
qobject/json-writer.c Normal file
View File

@ -0,0 +1,247 @@
/*
* JSON Writer
*
* Copyright IBM, Corp. 2009
* Copyright (c) 2010-2020 Red Hat Inc.
*
* Authors:
* Anthony Liguori <aliguori@us.ibm.com>
* Markus Armbruster <armbru@redhat.com>
*
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
* See the COPYING.LIB file in the top-level directory.
*
*/
#include "qemu/osdep.h"
#include "qapi/qmp/json-writer.h"
#include "qemu/unicode.h"
struct JSONWriter {
bool pretty;
bool need_comma;
GString *contents;
GByteArray *container_is_array;
};
JSONWriter *json_writer_new(bool pretty)
{
JSONWriter *writer = g_new(JSONWriter, 1);
writer->pretty = pretty;
writer->need_comma = false;
writer->contents = g_string_new(NULL);
writer->container_is_array = g_byte_array_new();
return writer;
}
const char *json_writer_get(JSONWriter *writer)
{
g_assert(!writer->container_is_array->len);
return writer->contents->str;
}
GString *json_writer_get_and_free(JSONWriter *writer)
{
GString *contents = writer->contents;
writer->contents = NULL;
g_byte_array_free(writer->container_is_array, true);
g_free(writer);
return contents;
}
void json_writer_free(JSONWriter *writer)
{
if (writer) {
g_string_free(json_writer_get_and_free(writer), true);
}
}
static void enter_container(JSONWriter *writer, bool is_array)
{
unsigned depth = writer->container_is_array->len;
g_byte_array_set_size(writer->container_is_array, depth + 1);
writer->container_is_array->data[depth] = is_array;
writer->need_comma = false;
}
static void leave_container(JSONWriter *writer, bool is_array)
{
unsigned depth = writer->container_is_array->len;
assert(depth);
assert(writer->container_is_array->data[depth - 1] == is_array);
g_byte_array_set_size(writer->container_is_array, depth - 1);
writer->need_comma = true;
}
static bool in_object(JSONWriter *writer)
{
unsigned depth = writer->container_is_array->len;
return depth && !writer->container_is_array->data[depth - 1];
}
static void pretty_newline(JSONWriter *writer)
{
if (writer->pretty) {
g_string_append_printf(writer->contents, "\n%*s",
writer->container_is_array->len * 4, "");
}
}
static void pretty_newline_or_space(JSONWriter *writer)
{
if (writer->pretty) {
g_string_append_printf(writer->contents, "\n%*s",
writer->container_is_array->len * 4, "");
} else {
g_string_append_c(writer->contents, ' ');
}
}
static void quoted_str(JSONWriter *writer, const char *str)
{
const char *ptr;
char *end;
int cp;
g_string_append_c(writer->contents, '"');
for (ptr = str; *ptr; ptr = end) {
cp = mod_utf8_codepoint(ptr, 6, &end);
switch (cp) {
case '\"':
g_string_append(writer->contents, "\\\"");
break;
case '\\':
g_string_append(writer->contents, "\\\\");
break;
case '\b':
g_string_append(writer->contents, "\\b");
break;
case '\f':
g_string_append(writer->contents, "\\f");
break;
case '\n':
g_string_append(writer->contents, "\\n");
break;
case '\r':
g_string_append(writer->contents, "\\r");
break;
case '\t':
g_string_append(writer->contents, "\\t");
break;
default:
if (cp < 0) {
cp = 0xFFFD; /* replacement character */
}
if (cp > 0xFFFF) {
/* beyond BMP; need a surrogate pair */
g_string_append_printf(writer->contents, "\\u%04X\\u%04X",
0xD800 + ((cp - 0x10000) >> 10),
0xDC00 + ((cp - 0x10000) & 0x3FF));
} else if (cp < 0x20 || cp >= 0x7F) {
g_string_append_printf(writer->contents, "\\u%04X", cp);
} else {
g_string_append_c(writer->contents, cp);
}
}
};
g_string_append_c(writer->contents, '"');
}
static void maybe_comma_name(JSONWriter *writer, const char *name)
{
if (writer->need_comma) {
g_string_append_c(writer->contents, ',');
pretty_newline_or_space(writer);
} else {
if (writer->contents->len) {
pretty_newline(writer);
}
writer->need_comma = true;
}
if (in_object(writer)) {
quoted_str(writer, name);
g_string_append(writer->contents, ": ");
}
}
void json_writer_start_object(JSONWriter *writer, const char *name)
{
maybe_comma_name(writer, name);
g_string_append_c(writer->contents, '{');
enter_container(writer, false);
}
void json_writer_end_object(JSONWriter *writer)
{
leave_container(writer, false);
pretty_newline(writer);
g_string_append_c(writer->contents, '}');
}
void json_writer_start_array(JSONWriter *writer, const char *name)
{
maybe_comma_name(writer, name);
g_string_append_c(writer->contents, '[');
enter_container(writer, true);
}
void json_writer_end_array(JSONWriter *writer)
{
leave_container(writer, true);
pretty_newline(writer);
g_string_append_c(writer->contents, ']');
}
void json_writer_bool(JSONWriter *writer, const char *name, bool val)
{
maybe_comma_name(writer, name);
g_string_append(writer->contents, val ? "true" : "false");
}
void json_writer_null(JSONWriter *writer, const char *name)
{
maybe_comma_name(writer, name);
g_string_append(writer->contents, "null");
}
void json_writer_int64(JSONWriter *writer, const char *name, int64_t val)
{
maybe_comma_name(writer, name);
g_string_append_printf(writer->contents, "%" PRId64, val);
}
void json_writer_uint64(JSONWriter *writer, const char *name, uint64_t val)
{
maybe_comma_name(writer, name);
g_string_append_printf(writer->contents, "%" PRIu64, val);
}
void json_writer_double(JSONWriter *writer, const char *name, double val)
{
maybe_comma_name(writer, name);
/*
* FIXME: g_string_append_printf() is locale dependent; but JSON
* requires numbers to be formatted as if in the C locale.
* Dependence on C locale is a pervasive issue in QEMU.
*/
/*
* FIXME: This risks printing Inf or NaN, which are not valid
* JSON values.
*/
g_string_append_printf(writer->contents, "%.17g", val);
}
void json_writer_str(JSONWriter *writer, const char *name, const char *str)
{
maybe_comma_name(writer, name);
quoted_str(writer, str);
}

View File

@ -1,3 +1,4 @@
util_ss.add(files('qnull.c', 'qnum.c', 'qstring.c', 'qdict.c', 'qlist.c', 'qbool.c', util_ss.add(files('qnull.c', 'qnum.c', 'qstring.c', 'qdict.c',
'qlit.c', 'qjson.c', 'qobject.c', 'json-lexer.c', 'json-streamer.c', 'json-parser.c', 'qlist.c', 'qbool.c', 'qlit.c', 'qjson.c', 'qobject.c',
'json-writer.c', 'json-lexer.c', 'json-streamer.c', 'json-parser.c',
'block-qdict.c')) 'block-qdict.c'))

View File

@ -13,6 +13,7 @@
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "qapi/qmp/qbool.h" #include "qapi/qmp/qbool.h"
#include "qobject-internal.h"
/** /**
* qbool_from_bool(): Create a new QBool from a bool * qbool_from_bool(): Create a new QBool from a bool

View File

@ -16,6 +16,7 @@
#include "qapi/qmp/qbool.h" #include "qapi/qmp/qbool.h"
#include "qapi/qmp/qnull.h" #include "qapi/qmp/qnull.h"
#include "qapi/qmp/qstring.h" #include "qapi/qmp/qstring.h"
#include "qobject-internal.h"
/** /**
* qdict_new(): Create a new QDict * qdict_new(): Create a new QDict

View File

@ -14,13 +14,13 @@
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "qapi/error.h" #include "qapi/error.h"
#include "qapi/qmp/json-parser.h" #include "qapi/qmp/json-parser.h"
#include "qapi/qmp/json-writer.h"
#include "qapi/qmp/qjson.h" #include "qapi/qmp/qjson.h"
#include "qapi/qmp/qbool.h" #include "qapi/qmp/qbool.h"
#include "qapi/qmp/qdict.h" #include "qapi/qmp/qdict.h"
#include "qapi/qmp/qlist.h" #include "qapi/qmp/qlist.h"
#include "qapi/qmp/qnum.h" #include "qapi/qmp/qnum.h"
#include "qapi/qmp/qstring.h" #include "qapi/qmp/qstring.h"
#include "qemu/unicode.h"
typedef struct JSONParsingState typedef struct JSONParsingState
{ {
@ -149,144 +149,69 @@ QDict *qdict_from_jsonf_nofail(const char *string, ...)
return qdict; return qdict;
} }
static void to_json(const QObject *obj, QString *str, int pretty, int indent); static void to_json(JSONWriter *writer, const char *name,
const QObject *obj)
static void json_pretty_newline(QString *str, bool pretty, int indent)
{
int i;
if (pretty) {
qstring_append(str, "\n");
for (i = 0; i < indent; i++) {
qstring_append(str, " ");
}
}
}
static void to_json(const QObject *obj, QString *str, int pretty, int indent)
{ {
switch (qobject_type(obj)) { switch (qobject_type(obj)) {
case QTYPE_QNULL: case QTYPE_QNULL:
qstring_append(str, "null"); json_writer_null(writer, name);
break; break;
case QTYPE_QNUM: { case QTYPE_QNUM: {
QNum *val = qobject_to(QNum, obj); QNum *val = qobject_to(QNum, obj);
char *buffer = qnum_to_string(val);
qstring_append(str, buffer); switch (val->kind) {
g_free(buffer); case QNUM_I64:
json_writer_int64(writer, name, val->u.i64);
break;
case QNUM_U64:
json_writer_uint64(writer, name, val->u.u64);
break;
case QNUM_DOUBLE:
json_writer_double(writer, name, val->u.dbl);
break;
default:
abort();
}
break; break;
} }
case QTYPE_QSTRING: { case QTYPE_QSTRING: {
QString *val = qobject_to(QString, obj); QString *val = qobject_to(QString, obj);
const char *ptr;
int cp;
char buf[16];
char *end;
ptr = qstring_get_str(val); json_writer_str(writer, name, qstring_get_str(val));
qstring_append(str, "\"");
for (; *ptr; ptr = end) {
cp = mod_utf8_codepoint(ptr, 6, &end);
switch (cp) {
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 (cp < 0) {
cp = 0xFFFD; /* replacement character */
}
if (cp > 0xFFFF) {
/* beyond BMP; need a surrogate pair */
snprintf(buf, sizeof(buf), "\\u%04X\\u%04X",
0xD800 + ((cp - 0x10000) >> 10),
0xDC00 + ((cp - 0x10000) & 0x3FF));
} else if (cp < 0x20 || cp >= 0x7F) {
snprintf(buf, sizeof(buf), "\\u%04X", cp);
} else {
buf[0] = cp;
buf[1] = 0;
}
qstring_append(str, buf);
}
};
qstring_append(str, "\"");
break; break;
} }
case QTYPE_QDICT: { case QTYPE_QDICT: {
QDict *val = qobject_to(QDict, obj); QDict *val = qobject_to(QDict, obj);
const char *comma = pretty ? "," : ", ";
const char *sep = "";
const QDictEntry *entry; const QDictEntry *entry;
QString *qkey;
qstring_append(str, "{"); json_writer_start_object(writer, name);
for (entry = qdict_first(val); for (entry = qdict_first(val);
entry; entry;
entry = qdict_next(val, entry)) { entry = qdict_next(val, entry)) {
qstring_append(str, sep); to_json(writer, qdict_entry_key(entry), qdict_entry_value(entry));
json_pretty_newline(str, pretty, indent + 1);
qkey = qstring_from_str(qdict_entry_key(entry));
to_json(QOBJECT(qkey), str, pretty, indent + 1);
qobject_unref(qkey);
qstring_append(str, ": ");
to_json(qdict_entry_value(entry), str, pretty, indent + 1);
sep = comma;
} }
json_pretty_newline(str, pretty, indent); json_writer_end_object(writer);
qstring_append(str, "}");
break; break;
} }
case QTYPE_QLIST: { case QTYPE_QLIST: {
QList *val = qobject_to(QList, obj); QList *val = qobject_to(QList, obj);
const char *comma = pretty ? "," : ", ";
const char *sep = "";
QListEntry *entry; QListEntry *entry;
qstring_append(str, "["); json_writer_start_array(writer, name);
QLIST_FOREACH_ENTRY(val, entry) { QLIST_FOREACH_ENTRY(val, entry) {
qstring_append(str, sep); to_json(writer, NULL, qlist_entry_obj(entry));
json_pretty_newline(str, pretty, indent + 1);
to_json(qlist_entry_obj(entry), str, pretty, indent + 1);
sep = comma;
} }
json_pretty_newline(str, pretty, indent); json_writer_end_array(writer);
qstring_append(str, "]");
break; break;
} }
case QTYPE_QBOOL: { case QTYPE_QBOOL: {
QBool *val = qobject_to(QBool, obj); QBool *val = qobject_to(QBool, obj);
if (qbool_get_bool(val)) { json_writer_bool(writer, name, qbool_get_bool(val));
qstring_append(str, "true");
} else {
qstring_append(str, "false");
}
break; break;
} }
default: default:
@ -294,20 +219,15 @@ static void to_json(const QObject *obj, QString *str, int pretty, int indent)
} }
} }
QString *qobject_to_json(const QObject *obj) GString *qobject_to_json_pretty(const QObject *obj, bool pretty)
{ {
QString *str = qstring_new(); JSONWriter *writer = json_writer_new(pretty);
to_json(obj, str, 0, 0); to_json(writer, NULL, obj);
return json_writer_get_and_free(writer);
return str;
} }
QString *qobject_to_json_pretty(const QObject *obj) GString *qobject_to_json(const QObject *obj)
{ {
QString *str = qstring_new(); return qobject_to_json_pretty(obj, false);
to_json(obj, str, 1, 0);
return str;
} }

View File

@ -17,6 +17,7 @@
#include "qapi/qmp/qnum.h" #include "qapi/qmp/qnum.h"
#include "qapi/qmp/qstring.h" #include "qapi/qmp/qstring.h"
#include "qemu/queue.h" #include "qemu/queue.h"
#include "qobject-internal.h"
/** /**
* qlist_new(): Create a new QList * qlist_new(): Create a new QList

View File

@ -12,6 +12,7 @@
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "qapi/qmp/qnull.h" #include "qapi/qmp/qnull.h"
#include "qobject-internal.h"
QNull qnull_ = { QNull qnull_ = {
.base = { .base = {

View File

@ -14,6 +14,7 @@
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "qapi/qmp/qnum.h" #include "qapi/qmp/qnum.h"
#include "qobject-internal.h"
/** /**
* qnum_from_int(): Create a new QNum from an int64_t * qnum_from_int(): Create a new QNum from an int64_t
@ -161,37 +162,14 @@ double qnum_get_double(QNum *qn)
char *qnum_to_string(QNum *qn) char *qnum_to_string(QNum *qn)
{ {
char *buffer;
int len;
switch (qn->kind) { switch (qn->kind) {
case QNUM_I64: case QNUM_I64:
return g_strdup_printf("%" PRId64, qn->u.i64); return g_strdup_printf("%" PRId64, qn->u.i64);
case QNUM_U64: case QNUM_U64:
return g_strdup_printf("%" PRIu64, qn->u.u64); return g_strdup_printf("%" PRIu64, qn->u.u64);
case QNUM_DOUBLE: case QNUM_DOUBLE:
/* FIXME: snprintf() is locale dependent; but JSON requires /* 17 digits suffice for IEEE double */
* numbers to be formatted as if in the C locale. Dependence return g_strdup_printf("%.17g", qn->u.dbl);
* on C locale is a pervasive issue in QEMU. */
/* FIXME: This risks printing Inf or NaN, which are not valid
* JSON values. */
/* FIXME: the default precision of 6 for %f often causes
* rounding errors; we should be using DBL_DECIMAL_DIG (17),
* and only rounding to a shorter number if the result would
* still produce the same floating point value. */
buffer = g_strdup_printf("%f" , qn->u.dbl);
len = strlen(buffer);
while (len > 0 && buffer[len - 1] == '0') {
len--;
}
if (len && buffer[len - 1] == '.') {
buffer[len - 1] = 0;
} else {
buffer[len] = 0;
}
return buffer;
} }
assert(0); assert(0);

View File

@ -0,0 +1,39 @@
/*
* QObject internals
*
* Copyright (C) 2015 Red Hat, Inc.
*
* This work is licensed under the terms of the GNU LGPL, version 2.1
* or later. See the COPYING.LIB file in the top-level directory.
*/
#ifndef QOBJECT_INTERNAL_H
#define QOBJECT_INTERNAL_H
#include "qapi/qmp/qobject.h"
static inline void qobject_init(QObject *obj, QType type)
{
assert(QTYPE_NONE < type && type < QTYPE__MAX);
obj->base.refcnt = 1;
obj->base.type = type;
}
void qbool_destroy_obj(QObject *obj);
bool qbool_is_equal(const QObject *x, const QObject *y);
void qdict_destroy_obj(QObject *obj);
bool qdict_is_equal(const QObject *x, const QObject *y);
void qlist_destroy_obj(QObject *obj);
bool qlist_is_equal(const QObject *x, const QObject *y);
bool qnull_is_equal(const QObject *x, const QObject *y);
void qnum_destroy_obj(QObject *obj);
bool qnum_is_equal(const QObject *x, const QObject *y);
void qstring_destroy_obj(QObject *obj);
bool qstring_is_equal(const QObject *x, const QObject *y);
#endif

View File

@ -14,6 +14,7 @@
#include "qapi/qmp/qdict.h" #include "qapi/qmp/qdict.h"
#include "qapi/qmp/qlist.h" #include "qapi/qmp/qlist.h"
#include "qapi/qmp/qstring.h" #include "qapi/qmp/qstring.h"
#include "qobject-internal.h"
QEMU_BUILD_BUG_MSG( QEMU_BUILD_BUG_MSG(
offsetof(QNull, base) != 0 || offsetof(QNull, base) != 0 ||

View File

@ -12,6 +12,7 @@
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "qapi/qmp/qstring.h" #include "qapi/qmp/qstring.h"
#include "qobject-internal.h"
/** /**
* qstring_new(): Create a new empty QString * qstring_new(): Create a new empty QString
@ -23,14 +24,6 @@ QString *qstring_new(void)
return qstring_from_str(""); return qstring_from_str("");
} }
/**
* qstring_get_length(): Get the length of a QString
*/
size_t qstring_get_length(const QString *qstring)
{
return qstring->length;
}
/** /**
* qstring_from_substr(): Create a new QString from a C string substring * qstring_from_substr(): Create a new QString from a C string substring
* *
@ -41,18 +34,9 @@ QString *qstring_from_substr(const char *str, size_t start, size_t end)
QString *qstring; QString *qstring;
assert(start <= end); assert(start <= end);
qstring = g_malloc(sizeof(*qstring)); qstring = g_malloc(sizeof(*qstring));
qobject_init(QOBJECT(qstring), QTYPE_QSTRING); qobject_init(QOBJECT(qstring), QTYPE_QSTRING);
qstring->string = g_strndup(str + start, end - start);
qstring->length = end - start;
qstring->capacity = qstring->length;
assert(qstring->capacity < SIZE_MAX);
qstring->string = g_malloc(qstring->capacity + 1);
memcpy(qstring->string, str + start, qstring->length);
qstring->string[qstring->length] = 0;
return qstring; return qstring;
} }
@ -66,48 +50,23 @@ QString *qstring_from_str(const char *str)
return qstring_from_substr(str, 0, strlen(str)); return qstring_from_substr(str, 0, strlen(str));
} }
static void capacity_increase(QString *qstring, size_t len)
{
if (qstring->capacity < (qstring->length + len)) {
assert(len <= SIZE_MAX - qstring->capacity);
qstring->capacity += len;
assert(qstring->capacity <= SIZE_MAX / 2);
qstring->capacity *= 2; /* use exponential growth */
qstring->string = g_realloc(qstring->string, qstring->capacity + 1);
}
}
/* qstring_append(): Append a C string to a QString
*/
void qstring_append(QString *qstring, const char *str)
{
size_t len = strlen(str);
capacity_increase(qstring, len);
memcpy(qstring->string + qstring->length, str, len);
qstring->length += len;
qstring->string[qstring->length] = 0;
}
void qstring_append_int(QString *qstring, int64_t value)
{
char num[32];
snprintf(num, sizeof(num), "%" PRId64, value);
qstring_append(qstring, num);
}
/** /**
* qstring_append_chr(): Append a C char to a QString * qstring_from_gstring(): Convert a GString to a QString
*
* Return strong reference.
*/ */
void qstring_append_chr(QString *qstring, int c)
QString *qstring_from_gstring(GString *gstr)
{ {
capacity_increase(qstring, 1); QString *qstring;
qstring->string[qstring->length++] = c;
qstring->string[qstring->length] = 0; qstring = g_malloc(sizeof(*qstring));
qobject_init(QOBJECT(qstring), QTYPE_QSTRING);
qstring->string = g_string_free(gstr, false);
return qstring;
} }
/** /**
* qstring_get_str(): Return a pointer to the stored string * qstring_get_str(): Return a pointer to the stored string
* *
@ -119,27 +78,6 @@ const char *qstring_get_str(const QString *qstring)
return qstring->string; return qstring->string;
} }
/**
* qstring_get_try_str(): Return a pointer to the stored string
*
* NOTE: will return NULL if qstring is not provided.
*/
const char *qstring_get_try_str(const QString *qstring)
{
return qstring ? qstring_get_str(qstring) : NULL;
}
/**
* qobject_get_try_str(): Return a pointer to the corresponding string
*
* NOTE: the string will only be returned if the object is valid, and
* its type is QString, otherwise NULL is returned.
*/
const char *qobject_get_try_str(const QObject *qstring)
{
return qstring_get_try_str(qobject_to(QString, qstring));
}
/** /**
* qstring_is_equal(): Test whether the two QStrings are equal * qstring_is_equal(): Test whether the two QStrings are equal
*/ */
@ -149,33 +87,16 @@ bool qstring_is_equal(const QObject *x, const QObject *y)
qobject_to(QString, y)->string); qobject_to(QString, y)->string);
} }
/**
* qstring_free(): Free the memory allocated by a QString object
*
* Return: if @return_str, return the underlying string, to be
* g_free(), otherwise NULL is returned.
*/
char *qstring_free(QString *qstring, bool return_str)
{
char *rv = NULL;
if (return_str) {
rv = qstring->string;
} else {
g_free(qstring->string);
}
g_free(qstring);
return rv;
}
/** /**
* qstring_destroy_obj(): Free all memory allocated by a QString * qstring_destroy_obj(): Free all memory allocated by a QString
* object * object
*/ */
void qstring_destroy_obj(QObject *obj) void qstring_destroy_obj(QObject *obj)
{ {
QString *qs;
assert(obj != NULL); assert(obj != NULL);
qstring_free(qobject_to(QString, obj), FALSE); qs = qobject_to(QString, obj);
g_free((char *)qs->string);
g_free(qs);
} }

View File

@ -1415,15 +1415,18 @@ char *object_property_get_str(Object *obj, const char *name,
Error **errp) Error **errp)
{ {
QObject *ret = object_property_get_qobject(obj, name, errp); QObject *ret = object_property_get_qobject(obj, name, errp);
QString *qstring;
char *retval; char *retval;
if (!ret) { if (!ret) {
return NULL; return NULL;
} }
qstring = qobject_to(QString, ret);
retval = g_strdup(qobject_get_try_str(ret)); if (!qstring) {
if (!retval) {
error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, "string"); error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, "string");
retval = NULL;
} else {
retval = g_strdup(qstring_get_str(qstring));
} }
qobject_unref(ret); qobject_unref(ret);

View File

@ -5,7 +5,6 @@
#include "qapi/qmp/qdict.h" #include "qapi/qmp/qdict.h"
#include "qapi/qmp/qerror.h" #include "qapi/qmp/qerror.h"
#include "qapi/qmp/qjson.h" #include "qapi/qmp/qjson.h"
#include "qapi/qmp/qstring.h"
#include "qapi/qobject-input-visitor.h" #include "qapi/qobject-input-visitor.h"
#include "qom/object_interfaces.h" #include "qom/object_interfaces.h"
#include "qemu/help_option.h" #include "qemu/help_option.h"
@ -207,7 +206,8 @@ char *object_property_help(const char *name, const char *type,
g_string_append(str, description); g_string_append(str, description);
} }
if (defval) { if (defval) {
g_autofree char *def_json = qstring_free(qobject_to_json(defval), TRUE); g_autofree char *def_json = g_string_free(qobject_to_json(defval),
true);
g_string_append_printf(str, " (default: %s)", def_json); g_string_append_printf(str, " (default: %s)", def_json);
} }

View File

@ -13,7 +13,6 @@
#include "qapi/qapi-commands-qom.h" #include "qapi/qapi-commands-qom.h"
#include "qapi/qmp/qdict.h" #include "qapi/qmp/qdict.h"
#include "qapi/qmp/qjson.h" #include "qapi/qmp/qjson.h"
#include "qapi/qmp/qstring.h"
#include "qom/object.h" #include "qom/object.h"
void hmp_qom_list(Monitor *mon, const QDict *qdict) void hmp_qom_list(Monitor *mon, const QDict *qdict)
@ -78,9 +77,9 @@ void hmp_qom_get(Monitor *mon, const QDict *qdict)
QObject *obj = qmp_qom_get(path, property, &err); QObject *obj = qmp_qom_get(path, property, &err);
if (err == NULL) { if (err == NULL) {
QString *str = qobject_to_json_pretty(obj); GString *str = qobject_to_json_pretty(obj, true);
monitor_printf(mon, "%s\n", qstring_get_str(str)); monitor_printf(mon, "%s\n", str->str);
qobject_unref(str); g_string_free(str, true);
} }
qobject_unref(obj); qobject_unref(obj);

View File

@ -46,14 +46,12 @@ ObjectPropertyInfoList *qmp_qom_list(const char *path, Error **errp)
object_property_iter_init(&iter, obj); object_property_iter_init(&iter, obj);
while ((prop = object_property_iter_next(&iter))) { while ((prop = object_property_iter_next(&iter))) {
ObjectPropertyInfoList *entry = g_malloc0(sizeof(*entry)); ObjectPropertyInfo *value = g_malloc0(sizeof(ObjectPropertyInfo));
entry->value = g_malloc0(sizeof(ObjectPropertyInfo)); QAPI_LIST_PREPEND(props, value);
entry->next = props;
props = entry;
entry->value->name = g_strdup(prop->name); value->name = g_strdup(prop->name);
entry->value->type = g_strdup(prop->type); value->type = g_strdup(prop->type);
} }
return props; return props;
@ -90,7 +88,7 @@ QObject *qmp_qom_get(const char *path, const char *property, Error **errp)
static void qom_list_types_tramp(ObjectClass *klass, void *data) static void qom_list_types_tramp(ObjectClass *klass, void *data)
{ {
ObjectTypeInfoList *e, **pret = data; ObjectTypeInfoList **pret = data;
ObjectTypeInfo *info; ObjectTypeInfo *info;
ObjectClass *parent = object_class_get_parent(klass); ObjectClass *parent = object_class_get_parent(klass);
@ -102,10 +100,7 @@ static void qom_list_types_tramp(ObjectClass *klass, void *data)
info->parent = g_strdup(object_class_get_name(parent)); info->parent = g_strdup(object_class_get_name(parent));
} }
e = g_malloc0(sizeof(*e)); QAPI_LIST_PREPEND(*pret, info);
e->value = info;
e->next = *pret;
*pret = e;
} }
ObjectTypeInfoList *qmp_qom_list_types(bool has_implements, ObjectTypeInfoList *qmp_qom_list_types(bool has_implements,
@ -150,7 +145,6 @@ ObjectPropertyInfoList *qmp_device_list_properties(const char *typename,
object_property_iter_init(&iter, obj); object_property_iter_init(&iter, obj);
while ((prop = object_property_iter_next(&iter))) { while ((prop = object_property_iter_next(&iter))) {
ObjectPropertyInfo *info; ObjectPropertyInfo *info;
ObjectPropertyInfoList *entry;
/* Skip Object and DeviceState properties */ /* Skip Object and DeviceState properties */
if (strcmp(prop->name, "type") == 0 || if (strcmp(prop->name, "type") == 0 ||
@ -176,10 +170,7 @@ ObjectPropertyInfoList *qmp_device_list_properties(const char *typename,
info->default_value = qobject_ref(prop->defval); info->default_value = qobject_ref(prop->defval);
info->has_default_value = !!info->default_value; info->has_default_value = !!info->default_value;
entry = g_malloc0(sizeof(*entry)); QAPI_LIST_PREPEND(prop_list, info);
entry->value = info;
entry->next = prop_list;
prop_list = entry;
} }
object_unref(obj); object_unref(obj);
@ -217,7 +208,6 @@ ObjectPropertyInfoList *qmp_qom_list_properties(const char *typename,
} }
while ((prop = object_property_iter_next(&iter))) { while ((prop = object_property_iter_next(&iter))) {
ObjectPropertyInfo *info; ObjectPropertyInfo *info;
ObjectPropertyInfoList *entry;
info = g_malloc0(sizeof(*info)); info = g_malloc0(sizeof(*info));
info->name = g_strdup(prop->name); info->name = g_strdup(prop->name);
@ -225,10 +215,7 @@ ObjectPropertyInfoList *qmp_qom_list_properties(const char *typename,
info->has_description = !!prop->description; info->has_description = !!prop->description;
info->description = g_strdup(prop->description); info->description = g_strdup(prop->description);
entry = g_malloc0(sizeof(*entry)); QAPI_LIST_PREPEND(prop_list, info);
entry->value = info;
entry->next = prop_list;
prop_list = entry;
} }
object_unref(obj); object_unref(obj);

View File

@ -11,7 +11,7 @@ static int get_fpcr(QEMUFile *f, void *opaque, size_t size,
} }
static int put_fpcr(QEMUFile *f, void *opaque, size_t size, static int put_fpcr(QEMUFile *f, void *opaque, size_t size,
const VMStateField *field, QJSON *vmdesc) const VMStateField *field, JSONWriter *vmdesc)
{ {
CPUAlphaState *env = opaque; CPUAlphaState *env = opaque;
qemu_put_be64(f, cpu_alpha_load_fpcr(env)); qemu_put_be64(f, cpu_alpha_load_fpcr(env));

View File

@ -8283,7 +8283,6 @@ static void arm_cpu_add_definition(gpointer data, gpointer user_data)
{ {
ObjectClass *oc = data; ObjectClass *oc = data;
CpuDefinitionInfoList **cpu_list = user_data; CpuDefinitionInfoList **cpu_list = user_data;
CpuDefinitionInfoList *entry;
CpuDefinitionInfo *info; CpuDefinitionInfo *info;
const char *typename; const char *typename;
@ -8293,10 +8292,7 @@ static void arm_cpu_add_definition(gpointer data, gpointer user_data)
strlen(typename) - strlen("-" TYPE_ARM_CPU)); strlen(typename) - strlen("-" TYPE_ARM_CPU));
info->q_typename = g_strdup(typename); info->q_typename = g_strdup(typename);
entry = g_malloc0(sizeof(*entry)); QAPI_LIST_PREPEND(*cpu_list, info);
entry->value = info;
entry->next = *cpu_list;
*cpu_list = entry;
} }
CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp) CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)

View File

@ -27,7 +27,7 @@ static int get_fpscr(QEMUFile *f, void *opaque, size_t size,
} }
static int put_fpscr(QEMUFile *f, void *opaque, size_t size, static int put_fpscr(QEMUFile *f, void *opaque, size_t size,
const VMStateField *field, QJSON *vmdesc) const VMStateField *field, JSONWriter *vmdesc)
{ {
ARMCPU *cpu = opaque; ARMCPU *cpu = opaque;
CPUARMState *env = &cpu->env; CPUARMState *env = &cpu->env;
@ -573,7 +573,7 @@ static int get_cpsr(QEMUFile *f, void *opaque, size_t size,
} }
static int put_cpsr(QEMUFile *f, void *opaque, size_t size, static int put_cpsr(QEMUFile *f, void *opaque, size_t size,
const VMStateField *field, QJSON *vmdesc) const VMStateField *field, JSONWriter *vmdesc)
{ {
ARMCPU *cpu = opaque; ARMCPU *cpu = opaque;
CPUARMState *env = &cpu->env; CPUARMState *env = &cpu->env;
@ -608,7 +608,7 @@ static int get_power(QEMUFile *f, void *opaque, size_t size,
} }
static int put_power(QEMUFile *f, void *opaque, size_t size, static int put_power(QEMUFile *f, void *opaque, size_t size,
const VMStateField *field, QJSON *vmdesc) const VMStateField *field, JSONWriter *vmdesc)
{ {
ARMCPU *cpu = opaque; ARMCPU *cpu = opaque;

View File

@ -42,15 +42,6 @@ static GICCapability *gic_cap_new(int version)
return cap; return cap;
} }
static GICCapabilityList *gic_cap_list_add(GICCapabilityList *head,
GICCapability *cap)
{
GICCapabilityList *item = g_new0(GICCapabilityList, 1);
item->value = cap;
item->next = head;
return item;
}
static inline void gic_cap_kvm_probe(GICCapability *v2, GICCapability *v3) static inline void gic_cap_kvm_probe(GICCapability *v2, GICCapability *v3)
{ {
#ifdef CONFIG_KVM #ifdef CONFIG_KVM
@ -84,8 +75,8 @@ GICCapabilityList *qmp_query_gic_capabilities(Error **errp)
gic_cap_kvm_probe(v2, v3); gic_cap_kvm_probe(v2, v3);
head = gic_cap_list_add(head, v2); QAPI_LIST_PREPEND(head, v2);
head = gic_cap_list_add(head, v3); QAPI_LIST_PREPEND(head, v3);
return head; return head;
} }

View File

@ -34,7 +34,7 @@ static int get_sreg(QEMUFile *f, void *opaque, size_t size,
} }
static int put_sreg(QEMUFile *f, void *opaque, size_t size, static int put_sreg(QEMUFile *f, void *opaque, size_t size,
const VMStateField *field, QJSON *vmdesc) const VMStateField *field, JSONWriter *vmdesc)
{ {
CPUAVRState *env = opaque; CPUAVRState *env = opaque;
uint8_t sreg = cpu_get_sreg(env); uint8_t sreg = cpu_get_sreg(env);
@ -61,7 +61,7 @@ static int get_segment(QEMUFile *f, void *opaque, size_t size,
} }
static int put_segment(QEMUFile *f, void *opaque, size_t size, static int put_segment(QEMUFile *f, void *opaque, size_t size,
const VMStateField *field, QJSON *vmdesc) const VMStateField *field, JSONWriter *vmdesc)
{ {
uint32_t *ramp = opaque; uint32_t *ramp = opaque;
uint8_t temp = *ramp >> 16; uint8_t temp = *ramp >> 16;

View File

@ -52,7 +52,7 @@ static int get_psw(QEMUFile *f, void *opaque, size_t size,
} }
static int put_psw(QEMUFile *f, void *opaque, size_t size, static int put_psw(QEMUFile *f, void *opaque, size_t size,
const VMStateField *field, QJSON *vmdesc) const VMStateField *field, JSONWriter *vmdesc)
{ {
CPUHPPAState *env = opaque; CPUHPPAState *env = opaque;
qemu_put_betr(f, cpu_hppa_get_psw(env)); qemu_put_betr(f, cpu_hppa_get_psw(env));
@ -93,7 +93,7 @@ static int get_tlb(QEMUFile *f, void *opaque, size_t size,
} }
static int put_tlb(QEMUFile *f, void *opaque, size_t size, static int put_tlb(QEMUFile *f, void *opaque, size_t size,
const VMStateField *field, QJSON *vmdesc) const VMStateField *field, JSONWriter *vmdesc)
{ {
hppa_tlb_entry *ent = opaque; hppa_tlb_entry *ent = opaque;
uint32_t val = 0; uint32_t val = 0;

View File

@ -5014,7 +5014,6 @@ static void x86_cpu_definition_entry(gpointer data, gpointer user_data)
ObjectClass *oc = data; ObjectClass *oc = data;
X86CPUClass *cc = X86_CPU_CLASS(oc); X86CPUClass *cc = X86_CPU_CLASS(oc);
CpuDefinitionInfoList **cpu_list = user_data; CpuDefinitionInfoList **cpu_list = user_data;
CpuDefinitionInfoList *entry;
CpuDefinitionInfo *info; CpuDefinitionInfo *info;
info = g_malloc0(sizeof(*info)); info = g_malloc0(sizeof(*info));
@ -5039,10 +5038,7 @@ static void x86_cpu_definition_entry(gpointer data, gpointer user_data)
info->has_alias_of = !!info->alias_of; info->has_alias_of = !!info->alias_of;
} }
entry = g_malloc0(sizeof(*entry)); QAPI_LIST_PREPEND(*cpu_list, info);
entry->value = info;
entry->next = *cpu_list;
*cpu_list = entry;
} }
CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp) CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)

View File

@ -46,7 +46,7 @@ static int get_msr(QEMUFile *f, void *opaque, size_t size,
} }
static int put_msr(QEMUFile *f, void *opaque, size_t size, static int put_msr(QEMUFile *f, void *opaque, size_t size,
const VMStateField *field, QJSON *vmdesc) const VMStateField *field, JSONWriter *vmdesc)
{ {
CPUMBState *env = container_of(opaque, CPUMBState, msr); CPUMBState *env = container_of(opaque, CPUMBState, msr);

View File

@ -543,7 +543,6 @@ static void mips_cpu_add_definition(gpointer data, gpointer user_data)
{ {
ObjectClass *oc = data; ObjectClass *oc = data;
CpuDefinitionInfoList **cpu_list = user_data; CpuDefinitionInfoList **cpu_list = user_data;
CpuDefinitionInfoList *entry;
CpuDefinitionInfo *info; CpuDefinitionInfo *info;
const char *typename; const char *typename;
@ -553,10 +552,7 @@ static void mips_cpu_add_definition(gpointer data, gpointer user_data)
strlen(typename) - strlen("-" TYPE_MIPS_CPU)); strlen(typename) - strlen("-" TYPE_MIPS_CPU));
info->q_typename = g_strdup(typename); info->q_typename = g_strdup(typename);
entry = g_malloc0(sizeof(*entry)); QAPI_LIST_PREPEND(*cpu_list, info);
entry->value = info;
entry->next = *cpu_list;
*cpu_list = entry;
} }
CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp) CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)

View File

@ -31,7 +31,7 @@ static int get_fpr(QEMUFile *f, void *pv, size_t size,
} }
static int put_fpr(QEMUFile *f, void *pv, size_t size, static int put_fpr(QEMUFile *f, void *pv, size_t size,
const VMStateField *field, QJSON *vmdesc) const VMStateField *field, JSONWriter *vmdesc)
{ {
int i; int i;
fpr_t *v = pv; fpr_t *v = pv;
@ -156,7 +156,7 @@ static int get_tlb(QEMUFile *f, void *pv, size_t size,
} }
static int put_tlb(QEMUFile *f, void *pv, size_t size, static int put_tlb(QEMUFile *f, void *pv, size_t size,
const VMStateField *field, QJSON *vmdesc) const VMStateField *field, JSONWriter *vmdesc)
{ {
r4k_tlb_t *v = pv; r4k_tlb_t *v = pv;

View File

@ -55,7 +55,7 @@ static int get_sr(QEMUFile *f, void *opaque, size_t size,
} }
static int put_sr(QEMUFile *f, void *opaque, size_t size, static int put_sr(QEMUFile *f, void *opaque, size_t size,
const VMStateField *field, QJSON *vmdesc) const VMStateField *field, JSONWriter *vmdesc)
{ {
CPUOpenRISCState *env = opaque; CPUOpenRISCState *env = opaque;
qemu_put_be32(f, cpu_get_sr(env)); qemu_put_be32(f, cpu_get_sr(env));

View File

@ -134,7 +134,7 @@ static int get_avr(QEMUFile *f, void *pv, size_t size,
} }
static int put_avr(QEMUFile *f, void *pv, size_t size, static int put_avr(QEMUFile *f, void *pv, size_t size,
const VMStateField *field, QJSON *vmdesc) const VMStateField *field, JSONWriter *vmdesc)
{ {
ppc_avr_t *v = pv; ppc_avr_t *v = pv;
@ -166,7 +166,7 @@ static int get_fpr(QEMUFile *f, void *pv, size_t size,
} }
static int put_fpr(QEMUFile *f, void *pv, size_t size, static int put_fpr(QEMUFile *f, void *pv, size_t size,
const VMStateField *field, QJSON *vmdesc) const VMStateField *field, JSONWriter *vmdesc)
{ {
ppc_vsr_t *v = pv; ppc_vsr_t *v = pv;
@ -197,7 +197,7 @@ static int get_vsr(QEMUFile *f, void *pv, size_t size,
} }
static int put_vsr(QEMUFile *f, void *pv, size_t size, static int put_vsr(QEMUFile *f, void *pv, size_t size,
const VMStateField *field, QJSON *vmdesc) const VMStateField *field, JSONWriter *vmdesc)
{ {
ppc_vsr_t *v = pv; ppc_vsr_t *v = pv;
@ -455,7 +455,7 @@ static int get_vscr(QEMUFile *f, void *opaque, size_t size,
} }
static int put_vscr(QEMUFile *f, void *opaque, size_t size, static int put_vscr(QEMUFile *f, void *opaque, size_t size,
const VMStateField *field, QJSON *vmdesc) const VMStateField *field, JSONWriter *vmdesc)
{ {
PowerPCCPU *cpu = opaque; PowerPCCPU *cpu = opaque;
qemu_put_be32(f, helper_mfvscr(&cpu->env)); qemu_put_be32(f, helper_mfvscr(&cpu->env));
@ -580,7 +580,7 @@ static int get_slbe(QEMUFile *f, void *pv, size_t size,
} }
static int put_slbe(QEMUFile *f, void *pv, size_t size, static int put_slbe(QEMUFile *f, void *pv, size_t size,
const VMStateField *field, QJSON *vmdesc) const VMStateField *field, JSONWriter *vmdesc)
{ {
ppc_slb_t *v = pv; ppc_slb_t *v = pv;

View File

@ -10566,7 +10566,6 @@ static void ppc_cpu_defs_entry(gpointer data, gpointer user_data)
ObjectClass *oc = data; ObjectClass *oc = data;
CpuDefinitionInfoList **first = user_data; CpuDefinitionInfoList **first = user_data;
const char *typename; const char *typename;
CpuDefinitionInfoList *entry;
CpuDefinitionInfo *info; CpuDefinitionInfo *info;
typename = object_class_get_name(oc); typename = object_class_get_name(oc);
@ -10574,10 +10573,7 @@ static void ppc_cpu_defs_entry(gpointer data, gpointer user_data)
info->name = g_strndup(typename, info->name = g_strndup(typename,
strlen(typename) - strlen(POWERPC_CPU_TYPE_SUFFIX)); strlen(typename) - strlen(POWERPC_CPU_TYPE_SUFFIX));
entry = g_malloc0(sizeof(*entry)); QAPI_LIST_PREPEND(*first, info);
entry->value = info;
entry->next = *first;
*first = entry;
} }
CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp) CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
@ -10593,7 +10589,6 @@ CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
for (i = 0; ppc_cpu_aliases[i].alias != NULL; i++) { for (i = 0; ppc_cpu_aliases[i].alias != NULL; i++) {
PowerPCCPUAlias *alias = &ppc_cpu_aliases[i]; PowerPCCPUAlias *alias = &ppc_cpu_aliases[i];
ObjectClass *oc; ObjectClass *oc;
CpuDefinitionInfoList *entry;
CpuDefinitionInfo *info; CpuDefinitionInfo *info;
oc = ppc_cpu_class_by_name(alias->model); oc = ppc_cpu_class_by_name(alias->model);
@ -10605,10 +10600,7 @@ CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
info->name = g_strdup(alias->alias); info->name = g_strdup(alias->alias);
info->q_typename = g_strdup(object_class_get_name(oc)); info->q_typename = g_strdup(object_class_get_name(oc));
entry = g_malloc0(sizeof(*entry)); QAPI_LIST_PREPEND(cpu_list, info);
entry->value = info;
entry->next = cpu_list;
cpu_list = entry;
} }
return cpu_list; return cpu_list;

View File

@ -427,7 +427,6 @@ static void create_cpu_model_list(ObjectClass *klass, void *opaque)
{ {
struct CpuDefinitionInfoListData *cpu_list_data = opaque; struct CpuDefinitionInfoListData *cpu_list_data = opaque;
CpuDefinitionInfoList **cpu_list = &cpu_list_data->list; CpuDefinitionInfoList **cpu_list = &cpu_list_data->list;
CpuDefinitionInfoList *entry;
CpuDefinitionInfo *info; CpuDefinitionInfo *info;
char *name = g_strdup(object_class_get_name(klass)); char *name = g_strdup(object_class_get_name(klass));
S390CPUClass *scc = S390_CPU_CLASS(klass); S390CPUClass *scc = S390_CPU_CLASS(klass);
@ -454,10 +453,7 @@ static void create_cpu_model_list(ObjectClass *klass, void *opaque)
object_unref(obj); object_unref(obj);
} }
entry = g_new0(CpuDefinitionInfoList, 1); QAPI_LIST_PREPEND(*cpu_list, info);
entry->value = info;
entry->next = *cpu_list;
*cpu_list = entry;
} }
CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp) CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
@ -624,12 +620,8 @@ CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
static void list_add_feat(const char *name, void *opaque) static void list_add_feat(const char *name, void *opaque)
{ {
strList **last = (strList **) opaque; strList **last = (strList **) opaque;
strList *entry;
entry = g_new0(strList, 1); QAPI_LIST_PREPEND(*last, g_strdup(name));
entry->value = g_strdup(name);
entry->next = *last;
*last = entry;
} }
CpuModelCompareInfo *qmp_query_cpu_model_comparison(CpuModelInfo *infoa, CpuModelCompareInfo *qmp_query_cpu_model_comparison(CpuModelInfo *infoa,

View File

@ -68,7 +68,7 @@ static int get_psr(QEMUFile *f, void *opaque, size_t size,
} }
static int put_psr(QEMUFile *f, void *opaque, size_t size, static int put_psr(QEMUFile *f, void *opaque, size_t size,
const VMStateField *field, QJSON *vmdesc) const VMStateField *field, JSONWriter *vmdesc)
{ {
SPARCCPU *cpu = opaque; SPARCCPU *cpu = opaque;
CPUSPARCState *env = &cpu->env; CPUSPARCState *env = &cpu->env;

View File

@ -35,17 +35,15 @@ static QString *from_json_str(const char *jstr, bool single, Error **errp)
static char *to_json_str(QString *str) static char *to_json_str(QString *str)
{ {
QString *json = qobject_to_json(QOBJECT(str)); GString *json = qobject_to_json(QOBJECT(str));
char *jstr;
if (!json) { if (!json) {
return NULL; return NULL;
} }
/* peel off double quotes */ /* peel off double quotes */
jstr = g_strndup(qstring_get_str(json) + 1, g_string_truncate(json, json->len - 1);
qstring_get_length(json) - 2); g_string_erase(json, 0, 1);
qobject_unref(json); return g_string_free(json, false);
return jstr;
} }
static void escaped_string(void) static void escaped_string(void)
@ -91,7 +89,7 @@ static void escaped_string(void)
for (j = 0; j < 2; j++) { for (j = 0; j < 2; j++) {
if (test_cases[i].utf8_out) { if (test_cases[i].utf8_out) {
cstr = from_json_str(test_cases[i].json_in, j, &error_abort); cstr = from_json_str(test_cases[i].json_in, j, &error_abort);
g_assert_cmpstr(qstring_get_try_str(cstr), g_assert_cmpstr(qstring_get_str(cstr),
==, test_cases[i].utf8_out); ==, test_cases[i].utf8_out);
if (!test_cases[i].skip) { if (!test_cases[i].skip) {
jstr = to_json_str(cstr); jstr = to_json_str(cstr);
@ -753,7 +751,7 @@ static void utf8_string(void)
/* Parse @json_in, expect @utf8_out */ /* Parse @json_in, expect @utf8_out */
if (utf8_out) { if (utf8_out) {
str = from_json_str(json_in, j, &error_abort); str = from_json_str(json_in, j, &error_abort);
g_assert_cmpstr(qstring_get_try_str(str), ==, utf8_out); g_assert_cmpstr(qstring_get_str(str), ==, utf8_out);
qobject_unref(str); qobject_unref(str);
} else { } else {
str = from_json_str(json_in, j, NULL); str = from_json_str(json_in, j, NULL);
@ -784,125 +782,129 @@ static void utf8_string(void)
/* Parse @json_out right back, unless it has replacements */ /* Parse @json_out right back, unless it has replacements */
if (!strstr(json_out, "\\uFFFD")) { if (!strstr(json_out, "\\uFFFD")) {
str = from_json_str(json_out, j, &error_abort); str = from_json_str(json_out, j, &error_abort);
g_assert_cmpstr(qstring_get_try_str(str), ==, utf8_in); g_assert_cmpstr(qstring_get_str(str), ==, utf8_in);
qobject_unref(str); qobject_unref(str);
} }
} }
} }
} }
static void simple_number(void) static void int_number(void)
{ {
int i;
struct { struct {
const char *encoded; const char *encoded;
int64_t decoded; int64_t decoded;
int skip; const char *reencoded;
} test_cases[] = { } test_cases[] = {
{ "0", 0 }, { "0", 0 },
{ "1234", 1234 }, { "1234", 1234 },
{ "1", 1 }, { "1", 1 },
{ "-32", -32 }, { "-32", -32 },
{ "-0", 0, .skip = 1 }, { "-0", 0, "0" },
{ }, {},
}; };
int i;
QNum *qnum;
int64_t ival;
uint64_t uval;
GString *str;
for (i = 0; test_cases[i].encoded; i++) { for (i = 0; test_cases[i].encoded; i++) {
QNum *qnum;
int64_t val;
qnum = qobject_to(QNum, qnum = qobject_to(QNum,
qobject_from_json(test_cases[i].encoded, qobject_from_json(test_cases[i].encoded,
&error_abort)); &error_abort));
g_assert(qnum); g_assert(qnum);
g_assert(qnum_get_try_int(qnum, &val)); g_assert(qnum_get_try_int(qnum, &ival));
g_assert_cmpint(val, ==, test_cases[i].decoded); g_assert_cmpint(ival, ==, test_cases[i].decoded);
if (test_cases[i].skip == 0) { if (test_cases[i].decoded >= 0) {
QString *str; g_assert(qnum_get_try_uint(qnum, &uval));
g_assert_cmpuint(uval, ==, (uint64_t)test_cases[i].decoded);
str = qobject_to_json(QOBJECT(qnum)); } else {
g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0); g_assert(!qnum_get_try_uint(qnum, &uval));
qobject_unref(str);
} }
g_assert_cmpfloat(qnum_get_double(qnum), ==,
(double)test_cases[i].decoded);
str = qobject_to_json(QOBJECT(qnum));
g_assert_cmpstr(str->str, ==,
test_cases[i].reencoded ?: test_cases[i].encoded);
g_string_free(str, true);
qobject_unref(qnum); qobject_unref(qnum);
} }
} }
static void large_number(void) static void uint_number(void)
{ {
const char *maxu64 = "18446744073709551615"; /* 2^64-1 */ struct {
const char *gtu64 = "18446744073709551616"; /* 2^64 */ const char *encoded;
const char *lti64 = "-9223372036854775809"; /* -2^63 - 1 */ uint64_t decoded;
const char *reencoded;
} test_cases[] = {
{ "9223372036854775808", (uint64_t)1 << 63 },
{ "18446744073709551615", UINT64_MAX },
{},
};
int i;
QNum *qnum; QNum *qnum;
QString *str;
uint64_t val;
int64_t ival; int64_t ival;
uint64_t uval;
GString *str;
qnum = qobject_to(QNum, qobject_from_json(maxu64, &error_abort)); for (i = 0; test_cases[i].encoded; i++) {
g_assert(qnum); qnum = qobject_to(QNum,
g_assert_cmpuint(qnum_get_uint(qnum), ==, 18446744073709551615U); qobject_from_json(test_cases[i].encoded,
g_assert(!qnum_get_try_int(qnum, &ival)); &error_abort));
g_assert(qnum);
g_assert(qnum_get_try_uint(qnum, &uval));
g_assert_cmpuint(uval, ==, test_cases[i].decoded);
g_assert(!qnum_get_try_int(qnum, &ival));
g_assert_cmpfloat(qnum_get_double(qnum), ==,
(double)test_cases[i].decoded);
str = qobject_to_json(QOBJECT(qnum)); str = qobject_to_json(QOBJECT(qnum));
g_assert_cmpstr(qstring_get_str(str), ==, maxu64); g_assert_cmpstr(str->str, ==,
qobject_unref(str); test_cases[i].reencoded ?: test_cases[i].encoded);
qobject_unref(qnum); g_string_free(str, true);
qnum = qobject_to(QNum, qobject_from_json(gtu64, &error_abort)); qobject_unref(qnum);
g_assert(qnum); }
g_assert_cmpfloat(qnum_get_double(qnum), ==, 18446744073709552e3);
g_assert(!qnum_get_try_uint(qnum, &val));
g_assert(!qnum_get_try_int(qnum, &ival));
str = qobject_to_json(QOBJECT(qnum));
g_assert_cmpstr(qstring_get_str(str), ==, gtu64);
qobject_unref(str);
qobject_unref(qnum);
qnum = qobject_to(QNum, qobject_from_json(lti64, &error_abort));
g_assert(qnum);
g_assert_cmpfloat(qnum_get_double(qnum), ==, -92233720368547758e2);
g_assert(!qnum_get_try_uint(qnum, &val));
g_assert(!qnum_get_try_int(qnum, &ival));
str = qobject_to_json(QOBJECT(qnum));
g_assert_cmpstr(qstring_get_str(str), ==, "-9223372036854775808");
qobject_unref(str);
qobject_unref(qnum);
} }
static void float_number(void) static void float_number(void)
{ {
int i;
struct { struct {
const char *encoded; const char *encoded;
double decoded; double decoded;
int skip; const char *reencoded;
} test_cases[] = { } test_cases[] = {
{ "32.43", 32.43 }, { "32.43", 32.43 },
{ "0.222", 0.222 }, { "0.222", 0.222 },
{ "-32.12313", -32.12313 }, { "-32.12313", -32.12313, "-32.123130000000003" },
{ "-32.20e-10", -32.20e-10, .skip = 1 }, { "-32.20e-10", -32.20e-10, "-3.22e-09" },
{ }, { "18446744073709551616", 0x1p64, "1.8446744073709552e+19" },
{ "-9223372036854775809", -0x1p63, "-9.2233720368547758e+18" },
{},
}; };
int i;
QNum *qnum;
int64_t ival;
uint64_t uval;
GString *str;
for (i = 0; test_cases[i].encoded; i++) { for (i = 0; test_cases[i].encoded; i++) {
QObject *obj; qnum = qobject_to(QNum,
QNum *qnum; qobject_from_json(test_cases[i].encoded,
&error_abort));
obj = qobject_from_json(test_cases[i].encoded, &error_abort);
qnum = qobject_to(QNum, obj);
g_assert(qnum); g_assert(qnum);
g_assert(qnum_get_double(qnum) == test_cases[i].decoded); g_assert_cmpfloat(qnum_get_double(qnum), ==, test_cases[i].decoded);
g_assert(!qnum_get_try_int(qnum, &ival));
g_assert(!qnum_get_try_uint(qnum, &uval));
if (test_cases[i].skip == 0) { str = qobject_to_json(QOBJECT(qnum));
QString *str; g_assert_cmpstr(str->str, ==,
test_cases[i].reencoded ?: test_cases[i].encoded);
str = qobject_to_json(obj); g_string_free(str, true);
g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
qobject_unref(str);
}
qobject_unref(qnum); qobject_unref(qnum);
} }
@ -913,7 +915,7 @@ static void keyword_literal(void)
QObject *obj; QObject *obj;
QBool *qbool; QBool *qbool;
QNull *null; QNull *null;
QString *str; GString *str;
obj = qobject_from_json("true", &error_abort); obj = qobject_from_json("true", &error_abort);
qbool = qobject_to(QBool, obj); qbool = qobject_to(QBool, obj);
@ -921,8 +923,8 @@ static void keyword_literal(void)
g_assert(qbool_get_bool(qbool) == true); g_assert(qbool_get_bool(qbool) == true);
str = qobject_to_json(obj); str = qobject_to_json(obj);
g_assert(strcmp(qstring_get_str(str), "true") == 0); g_assert_cmpstr(str->str, ==, "true");
qobject_unref(str); g_string_free(str, true);
qobject_unref(qbool); qobject_unref(qbool);
@ -932,8 +934,8 @@ static void keyword_literal(void)
g_assert(qbool_get_bool(qbool) == false); g_assert(qbool_get_bool(qbool) == false);
str = qobject_to_json(obj); str = qobject_to_json(obj);
g_assert(strcmp(qstring_get_str(str), "false") == 0); g_assert_cmpstr(str->str, ==, "false");
qobject_unref(str); g_string_free(str, true);
qobject_unref(qbool); qobject_unref(qbool);
@ -1019,9 +1021,8 @@ static void interpolation_valid(void)
/* string */ /* string */
qstr = qobject_to(QString, qstr = qobject_to(QString, qobject_from_jsonf_nofail("%s", value_s));
qobject_from_jsonf_nofail("%s", value_s)); g_assert_cmpstr(qstring_get_str(qstr), ==, value_s);
g_assert_cmpstr(qstring_get_try_str(qstr), ==, value_s);
qobject_unref(qstr); qobject_unref(qstr);
/* object */ /* object */
@ -1083,7 +1084,7 @@ static void simple_dict(void)
for (i = 0; test_cases[i].encoded; i++) { for (i = 0; test_cases[i].encoded; i++) {
QObject *obj; QObject *obj;
QString *str; GString *str;
obj = qobject_from_json(test_cases[i].encoded, &error_abort); obj = qobject_from_json(test_cases[i].encoded, &error_abort);
g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj)); g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
@ -1091,10 +1092,10 @@ static void simple_dict(void)
str = qobject_to_json(obj); str = qobject_to_json(obj);
qobject_unref(obj); qobject_unref(obj);
obj = qobject_from_json(qstring_get_str(str), &error_abort); obj = qobject_from_json(str->str, &error_abort);
g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj)); g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
qobject_unref(obj); qobject_unref(obj);
qobject_unref(str); g_string_free(str, true);
} }
} }
@ -1192,7 +1193,7 @@ static void simple_list(void)
for (i = 0; test_cases[i].encoded; i++) { for (i = 0; test_cases[i].encoded; i++) {
QObject *obj; QObject *obj;
QString *str; GString *str;
obj = qobject_from_json(test_cases[i].encoded, &error_abort); obj = qobject_from_json(test_cases[i].encoded, &error_abort);
g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj)); g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
@ -1200,10 +1201,10 @@ static void simple_list(void)
str = qobject_to_json(obj); str = qobject_to_json(obj);
qobject_unref(obj); qobject_unref(obj);
obj = qobject_from_json(qstring_get_str(str), &error_abort); obj = qobject_from_json(str->str, &error_abort);
g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj)); g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
qobject_unref(obj); qobject_unref(obj);
qobject_unref(str); g_string_free(str, true);
} }
} }
@ -1254,7 +1255,7 @@ static void simple_whitespace(void)
for (i = 0; test_cases[i].encoded; i++) { for (i = 0; test_cases[i].encoded; i++) {
QObject *obj; QObject *obj;
QString *str; GString *str;
obj = qobject_from_json(test_cases[i].encoded, &error_abort); obj = qobject_from_json(test_cases[i].encoded, &error_abort);
g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj)); g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
@ -1262,11 +1263,11 @@ static void simple_whitespace(void)
str = qobject_to_json(obj); str = qobject_to_json(obj);
qobject_unref(obj); qobject_unref(obj);
obj = qobject_from_json(qstring_get_str(str), &error_abort); obj = qobject_from_json(str->str, &error_abort);
g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj)); g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
qobject_unref(obj); qobject_unref(obj);
qobject_unref(str); g_string_free(str, true);
} }
} }
@ -1479,8 +1480,8 @@ int main(int argc, char **argv)
g_test_add_func("/literals/string/quotes", string_with_quotes); g_test_add_func("/literals/string/quotes", string_with_quotes);
g_test_add_func("/literals/string/utf8", utf8_string); g_test_add_func("/literals/string/utf8", utf8_string);
g_test_add_func("/literals/number/simple", simple_number); g_test_add_func("/literals/number/int", int_number);
g_test_add_func("/literals/number/large", large_number); g_test_add_func("/literals/number/uint", uint_number);
g_test_add_func("/literals/number/float", float_number); g_test_add_func("/literals/number/float", float_number);
g_test_add_func("/literals/keyword", keyword_literal); g_test_add_func("/literals/keyword", keyword_literal);

View File

@ -147,7 +147,13 @@ static void qnum_to_string_test(void)
qn = qnum_from_double(0.42); qn = qnum_from_double(0.42);
tmp = qnum_to_string(qn); tmp = qnum_to_string(qn);
g_assert_cmpstr(tmp, ==, "0.42"); g_assert_cmpstr(tmp, ==, "0.41999999999999998");
g_free(tmp);
qobject_unref(qn);
qn = qnum_from_double(2.718281828459045);
tmp = qnum_to_string(qn);
g_assert_cmpstr(tmp, ==, "2.7182818284590451");
g_free(tmp); g_free(tmp);
qobject_unref(qn); qobject_unref(qn);
} }

View File

@ -155,8 +155,7 @@ static void qobject_is_equal_string_test(void)
str_case = qstring_from_str("Foo"); str_case = qstring_from_str("Foo");
/* Should yield "foo" */ /* Should yield "foo" */
str_built = qstring_from_substr("form", 0, 2); str_built = qstring_from_substr("buffoon", 3, 6);
qstring_append_chr(str_built, 'o');
check_unequal(str_base, str_whitespace_0, str_whitespace_1, check_unequal(str_base, str_whitespace_0, str_whitespace_1,
str_whitespace_2, str_whitespace_3, str_case); str_whitespace_2, str_whitespace_3, str_case);

View File

@ -47,21 +47,6 @@ static void qstring_get_str_test(void)
qobject_unref(qstring); qobject_unref(qstring);
} }
static void qstring_append_chr_test(void)
{
int i;
QString *qstring;
const char *str = "qstring append char unit-test";
qstring = qstring_new();
for (i = 0; str[i]; i++)
qstring_append_chr(qstring, str[i]);
g_assert(strcmp(str, qstring_get_str(qstring)) == 0);
qobject_unref(qstring);
}
static void qstring_from_substr_test(void) static void qstring_from_substr_test(void)
{ {
QString *qs; QString *qs;
@ -90,7 +75,6 @@ int main(int argc, char **argv)
g_test_add_func("/public/from_str", qstring_from_str_test); g_test_add_func("/public/from_str", qstring_from_str_test);
g_test_add_func("/public/get_str", qstring_get_str_test); g_test_add_func("/public/get_str", qstring_get_str_test);
g_test_add_func("/public/append_chr", qstring_append_chr_test);
g_test_add_func("/public/from_substr", qstring_from_substr_test); g_test_add_func("/public/from_substr", qstring_from_substr_test);
g_test_add_func("/public/to_qstring", qobject_to_qstring_test); g_test_add_func("/public/to_qstring", qobject_to_qstring_test);

View File

@ -652,27 +652,25 @@ void qmp_fd_vsend_fds(int fd, int *fds, size_t fds_num,
/* No need to send anything for an empty QObject. */ /* No need to send anything for an empty QObject. */
if (qobj) { if (qobj) {
int log = getenv("QTEST_LOG") != NULL; int log = getenv("QTEST_LOG") != NULL;
QString *qstr = qobject_to_json(qobj); GString *str = qobject_to_json(qobj);
const char *str;
/* /*
* BUG: QMP doesn't react to input until it sees a newline, an * BUG: QMP doesn't react to input until it sees a newline, an
* object, or an array. Work-around: give it a newline. * object, or an array. Work-around: give it a newline.
*/ */
qstring_append_chr(qstr, '\n'); g_string_append_c(str, '\n');
str = qstring_get_str(qstr);
if (log) { if (log) {
fprintf(stderr, "%s", str); fprintf(stderr, "%s", str->str);
} }
/* Send QMP request */ /* Send QMP request */
if (fds && fds_num > 0) { if (fds && fds_num > 0) {
socket_send_fds(fd, fds, fds_num, str, qstring_get_length(qstr)); socket_send_fds(fd, fds, fds_num, str->str, str->len);
} else { } else {
socket_send(fd, str, qstring_get_length(qstr)); socket_send(fd, str->str, str->len);
} }
qobject_unref(qstr); g_string_free(str, true);
qobject_unref(qobj); qobject_unref(qobj);
} }
} }
@ -1197,9 +1195,9 @@ void qtest_qmp_assert_success(QTestState *qts, const char *fmt, ...)
g_assert(response); g_assert(response);
if (!qdict_haskey(response, "return")) { if (!qdict_haskey(response, "return")) {
QString *s = qobject_to_json_pretty(QOBJECT(response)); GString *s = qobject_to_json_pretty(QOBJECT(response), true);
g_test_message("%s", qstring_get_str(s)); g_test_message("%s", s->str);
qobject_unref(s); g_string_free(s, true);
} }
g_assert(qdict_haskey(response, "return")); g_assert(qdict_haskey(response, "return"));
qobject_unref(response); qobject_unref(response);

View File

@ -65,16 +65,13 @@ static void test_clone_alternate(void)
static void test_clone_list_union(void) static void test_clone_list_union(void)
{ {
uint8List *src, *dst; uint8List *src = NULL, *dst;
uint8List *tmp = NULL; uint8List *tmp = NULL;
int i; int i;
/* Build list in reverse */ /* Build list in reverse */
for (i = 10; i; i--) { for (i = 10; i; i--) {
src = g_new0(uint8List, 1); QAPI_LIST_PREPEND(src, i);
src->next = tmp;
src->value = i;
tmp = src;
} }
dst = QAPI_CLONE(uint8List, src); dst = QAPI_CLONE(uint8List, src);

View File

@ -223,7 +223,8 @@ static void test_visitor_out_list(TestOutputVisitorData *data,
const void *unused) const void *unused)
{ {
const char *value_str = "list value"; const char *value_str = "list value";
TestStructList *p, *head = NULL; TestStruct *value;
TestStructList *head = NULL;
const int max_items = 10; const int max_items = 10;
bool value_bool = true; bool value_bool = true;
int value_int = 10; int value_int = 10;
@ -233,14 +234,12 @@ static void test_visitor_out_list(TestOutputVisitorData *data,
/* Build the list in reverse order... */ /* Build the list in reverse order... */
for (i = 0; i < max_items; i++) { for (i = 0; i < max_items; i++) {
p = g_malloc0(sizeof(*p)); value = g_malloc0(sizeof(*value));
p->value = g_malloc0(sizeof(*p->value)); value->integer = value_int + (max_items - i - 1);
p->value->integer = value_int + (max_items - i - 1); value->boolean = value_bool;
p->value->boolean = value_bool; value->string = g_strdup(value_str);
p->value->string = g_strdup(value_str);
p->next = head; QAPI_LIST_PREPEND(head, value);
head = p;
} }
visit_type_TestStructList(data->ov, NULL, &head, &error_abort); visit_type_TestStructList(data->ov, NULL, &head, &error_abort);
@ -270,26 +269,25 @@ static void test_visitor_out_list(TestOutputVisitorData *data,
static void test_visitor_out_list_qapi_free(TestOutputVisitorData *data, static void test_visitor_out_list_qapi_free(TestOutputVisitorData *data,
const void *unused) const void *unused)
{ {
UserDefTwoList *p, *head = NULL; UserDefTwo *value;
UserDefTwoList *head = NULL;
const char string[] = "foo bar"; const char string[] = "foo bar";
int i, max_count = 1024; int i, max_count = 1024;
for (i = 0; i < max_count; i++) { for (i = 0; i < max_count; i++) {
p = g_malloc0(sizeof(*p)); value = g_malloc0(sizeof(*value));
p->value = g_malloc0(sizeof(*p->value));
p->value->string0 = g_strdup(string); value->string0 = g_strdup(string);
p->value->dict1 = g_new0(UserDefTwoDict, 1); value->dict1 = g_new0(UserDefTwoDict, 1);
p->value->dict1->string1 = g_strdup(string); value->dict1->string1 = g_strdup(string);
p->value->dict1->dict2 = g_new0(UserDefTwoDictDict, 1); value->dict1->dict2 = g_new0(UserDefTwoDictDict, 1);
p->value->dict1->dict2->userdef = g_new0(UserDefOne, 1); value->dict1->dict2->userdef = g_new0(UserDefOne, 1);
p->value->dict1->dict2->userdef->string = g_strdup(string); value->dict1->dict2->userdef->string = g_strdup(string);
p->value->dict1->dict2->userdef->integer = 42; value->dict1->dict2->userdef->integer = 42;
p->value->dict1->dict2->string = g_strdup(string); value->dict1->dict2->string = g_strdup(string);
p->value->dict1->has_dict3 = false; value->dict1->has_dict3 = false;
p->next = head; QAPI_LIST_PREPEND(head, value);
head = p;
} }
qapi_free_UserDefTwoList(head); qapi_free_UserDefTwoList(head);

View File

@ -130,13 +130,13 @@ static void test_visitor_out_bool(TestOutputVisitorData *data,
static void test_visitor_out_number(TestOutputVisitorData *data, static void test_visitor_out_number(TestOutputVisitorData *data,
const void *unused) const void *unused)
{ {
double value = 3.14; double value = 3.1415926535897932;
char *str; char *str;
visit_type_number(data->ov, NULL, &value, &error_abort); visit_type_number(data->ov, NULL, &value, &error_abort);
str = visitor_get(data); str = visitor_get(data);
g_assert_cmpstr(str, ==, "3.140000"); g_assert_cmpstr(str, ==, "3.1415926535897931");
} }
static void test_visitor_out_string(TestOutputVisitorData *data, static void test_visitor_out_string(TestOutputVisitorData *data,

View File

@ -55,7 +55,6 @@ typedef struct PrimitiveType {
int16_t s16; int16_t s16;
int32_t s32; int32_t s32;
int64_t s64; int64_t s64;
intmax_t max;
} value; } value;
enum PrimitiveTypeKind type; enum PrimitiveTypeKind type;
const char *description; const char *description;
@ -307,25 +306,46 @@ static void test_primitives(gconstpointer opaque)
&error_abort); &error_abort);
g_assert(pt_copy != NULL); g_assert(pt_copy != NULL);
if (pt->type == PTYPE_STRING) { switch (pt->type) {
case PTYPE_STRING:
g_assert_cmpstr(pt->value.string, ==, pt_copy->value.string); g_assert_cmpstr(pt->value.string, ==, pt_copy->value.string);
g_free((char *)pt_copy->value.string); g_free((char *)pt_copy->value.string);
} else if (pt->type == PTYPE_NUMBER) { break;
GString *double_expected = g_string_new(""); case PTYPE_BOOLEAN:
GString *double_actual = g_string_new(""); g_assert_cmpint(pt->value.boolean, ==, pt->value.boolean);
/* we serialize with %f for our reference visitors, so rather than fuzzy break;
* floating math to test "equality", just compare the formatted values case PTYPE_NUMBER:
*/ g_assert_cmpfloat(pt->value.number, ==, pt_copy->value.number);
g_string_printf(double_expected, "%.6f", pt->value.number); break;
g_string_printf(double_actual, "%.6f", pt_copy->value.number); case PTYPE_INTEGER:
g_assert_cmpstr(double_actual->str, ==, double_expected->str); g_assert_cmpint(pt->value.integer, ==, pt_copy->value.integer);
break;
g_string_free(double_expected, true); case PTYPE_U8:
g_string_free(double_actual, true); g_assert_cmpuint(pt->value.u8, ==, pt_copy->value.u8);
} else if (pt->type == PTYPE_BOOLEAN) { break;
g_assert_cmpint(!!pt->value.max, ==, !!pt->value.max); case PTYPE_U16:
} else { g_assert_cmpuint(pt->value.u16, ==, pt_copy->value.u16);
g_assert_cmpint(pt->value.max, ==, pt_copy->value.max); break;
case PTYPE_U32:
g_assert_cmpuint(pt->value.u32, ==, pt_copy->value.u32);
break;
case PTYPE_U64:
g_assert_cmpuint(pt->value.u64, ==, pt_copy->value.u64);
break;
case PTYPE_S8:
g_assert_cmpint(pt->value.s8, ==, pt_copy->value.s8);
break;
case PTYPE_S16:
g_assert_cmpint(pt->value.s16, ==, pt_copy->value.s16);
break;
case PTYPE_S32:
g_assert_cmpint(pt->value.s32, ==, pt_copy->value.s32);
break;
case PTYPE_S64:
g_assert_cmpint(pt->value.s64, ==, pt_copy->value.s64);
break;
case PTYPE_EOL:
g_assert_not_reached();
} }
ops->cleanup(serialize_data); ops->cleanup(serialize_data);
@ -351,135 +371,51 @@ static void test_primitive_lists(gconstpointer opaque)
for (i = 0; i < 32; i++) { for (i = 0; i < 32; i++) {
switch (pl.type) { switch (pl.type) {
case PTYPE_STRING: { case PTYPE_STRING: {
strList *tmp = g_new0(strList, 1); QAPI_LIST_PREPEND(pl.value.strings, g_strdup(pt->value.string));
tmp->value = g_strdup(pt->value.string);
if (pl.value.strings == NULL) {
pl.value.strings = tmp;
} else {
tmp->next = pl.value.strings;
pl.value.strings = tmp;
}
break; break;
} }
case PTYPE_INTEGER: { case PTYPE_INTEGER: {
intList *tmp = g_new0(intList, 1); QAPI_LIST_PREPEND(pl.value.integers, pt->value.integer);
tmp->value = pt->value.integer;
if (pl.value.integers == NULL) {
pl.value.integers = tmp;
} else {
tmp->next = pl.value.integers;
pl.value.integers = tmp;
}
break; break;
} }
case PTYPE_S8: { case PTYPE_S8: {
int8List *tmp = g_new0(int8List, 1); QAPI_LIST_PREPEND(pl.value.s8_integers, pt->value.s8);
tmp->value = pt->value.s8;
if (pl.value.s8_integers == NULL) {
pl.value.s8_integers = tmp;
} else {
tmp->next = pl.value.s8_integers;
pl.value.s8_integers = tmp;
}
break; break;
} }
case PTYPE_S16: { case PTYPE_S16: {
int16List *tmp = g_new0(int16List, 1); QAPI_LIST_PREPEND(pl.value.s16_integers, pt->value.s16);
tmp->value = pt->value.s16;
if (pl.value.s16_integers == NULL) {
pl.value.s16_integers = tmp;
} else {
tmp->next = pl.value.s16_integers;
pl.value.s16_integers = tmp;
}
break; break;
} }
case PTYPE_S32: { case PTYPE_S32: {
int32List *tmp = g_new0(int32List, 1); QAPI_LIST_PREPEND(pl.value.s32_integers, pt->value.s32);
tmp->value = pt->value.s32;
if (pl.value.s32_integers == NULL) {
pl.value.s32_integers = tmp;
} else {
tmp->next = pl.value.s32_integers;
pl.value.s32_integers = tmp;
}
break; break;
} }
case PTYPE_S64: { case PTYPE_S64: {
int64List *tmp = g_new0(int64List, 1); QAPI_LIST_PREPEND(pl.value.s64_integers, pt->value.s64);
tmp->value = pt->value.s64;
if (pl.value.s64_integers == NULL) {
pl.value.s64_integers = tmp;
} else {
tmp->next = pl.value.s64_integers;
pl.value.s64_integers = tmp;
}
break; break;
} }
case PTYPE_U8: { case PTYPE_U8: {
uint8List *tmp = g_new0(uint8List, 1); QAPI_LIST_PREPEND(pl.value.u8_integers, pt->value.u8);
tmp->value = pt->value.u8;
if (pl.value.u8_integers == NULL) {
pl.value.u8_integers = tmp;
} else {
tmp->next = pl.value.u8_integers;
pl.value.u8_integers = tmp;
}
break; break;
} }
case PTYPE_U16: { case PTYPE_U16: {
uint16List *tmp = g_new0(uint16List, 1); QAPI_LIST_PREPEND(pl.value.u16_integers, pt->value.u16);
tmp->value = pt->value.u16;
if (pl.value.u16_integers == NULL) {
pl.value.u16_integers = tmp;
} else {
tmp->next = pl.value.u16_integers;
pl.value.u16_integers = tmp;
}
break; break;
} }
case PTYPE_U32: { case PTYPE_U32: {
uint32List *tmp = g_new0(uint32List, 1); QAPI_LIST_PREPEND(pl.value.u32_integers, pt->value.u32);
tmp->value = pt->value.u32;
if (pl.value.u32_integers == NULL) {
pl.value.u32_integers = tmp;
} else {
tmp->next = pl.value.u32_integers;
pl.value.u32_integers = tmp;
}
break; break;
} }
case PTYPE_U64: { case PTYPE_U64: {
uint64List *tmp = g_new0(uint64List, 1); QAPI_LIST_PREPEND(pl.value.u64_integers, pt->value.u64);
tmp->value = pt->value.u64;
if (pl.value.u64_integers == NULL) {
pl.value.u64_integers = tmp;
} else {
tmp->next = pl.value.u64_integers;
pl.value.u64_integers = tmp;
}
break; break;
} }
case PTYPE_NUMBER: { case PTYPE_NUMBER: {
numberList *tmp = g_new0(numberList, 1); QAPI_LIST_PREPEND(pl.value.numbers, pt->value.number);
tmp->value = pt->value.number;
if (pl.value.numbers == NULL) {
pl.value.numbers = tmp;
} else {
tmp->next = pl.value.numbers;
pl.value.numbers = tmp;
}
break; break;
} }
case PTYPE_BOOLEAN: { case PTYPE_BOOLEAN: {
boolList *tmp = g_new0(boolList, 1); QAPI_LIST_PREPEND(pl.value.booleans, pt->value.boolean);
tmp->value = pt->value.boolean;
if (pl.value.booleans == NULL) {
pl.value.booleans = tmp;
} else {
tmp->next = pl.value.booleans;
pl.value.booleans = tmp;
}
break; break;
} }
default: default:
@ -704,10 +640,7 @@ static void test_nested_struct_list(gconstpointer opaque)
int i = 0; int i = 0;
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
tmp = g_new0(UserDefTwoList, 1); QAPI_LIST_PREPEND(listp, nested_struct_create());
tmp->value = nested_struct_create();
tmp->next = listp;
listp = tmp;
} }
ops->serialize(listp, &serialize_data, visit_nested_struct_list, ops->serialize(listp, &serialize_data, visit_nested_struct_list,
@ -790,10 +723,6 @@ static PrimitiveType pt_values[] = {
.value.boolean = 0, .value.boolean = 0,
}, },
/* number tests (double) */ /* number tests (double) */
/* note: we format these to %.6f before comparing, since that's how
* we serialize them and it doesn't make sense to check precision
* beyond that.
*/
{ {
.description = "number_sanity1", .description = "number_sanity1",
.type = PTYPE_NUMBER, .type = PTYPE_NUMBER,
@ -802,7 +731,7 @@ static PrimitiveType pt_values[] = {
{ {
.description = "number_sanity2", .description = "number_sanity2",
.type = PTYPE_NUMBER, .type = PTYPE_NUMBER,
.value.number = 3.14159265, .value.number = 3.141593,
}, },
{ {
.description = "number_min", .description = "number_min",
@ -1028,15 +957,15 @@ static void qmp_deserialize(void **native_out, void *datap,
VisitorFunc visit, Error **errp) VisitorFunc visit, Error **errp)
{ {
QmpSerializeData *d = datap; QmpSerializeData *d = datap;
QString *output_json; GString *output_json;
QObject *obj_orig, *obj; QObject *obj_orig, *obj;
visit_complete(d->qov, &d->obj); visit_complete(d->qov, &d->obj);
obj_orig = d->obj; obj_orig = d->obj;
output_json = qobject_to_json(obj_orig); output_json = qobject_to_json(obj_orig);
obj = qobject_from_json(qstring_get_str(output_json), &error_abort); obj = qobject_from_json(output_json->str, &error_abort);
qobject_unref(output_json); g_string_free(output_json, true);
d->qiv = qobject_input_visitor_new(obj); d->qiv = qobject_input_visitor_new(obj);
qobject_unref(obj_orig); qobject_unref(obj_orig);
qobject_unref(obj); qobject_unref(obj);

Some files were not shown because too many files have changed in this diff Show More