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:
commit
1f7c02797f
23
block.c
23
block.c
@ -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
|
||||
* prefix being (wrongly) detected (if the filename contains a colon) */
|
||||
if (path_has_protocol(filename)) {
|
||||
QString *fat_filename;
|
||||
GString *fat_filename;
|
||||
|
||||
/* This means there is some colon before the first slash; therefore,
|
||||
* 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
|
||||
* by "./" */
|
||||
fat_filename = qstring_from_str("./");
|
||||
qstring_append(fat_filename, filename);
|
||||
fat_filename = g_string_new("./");
|
||||
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 {
|
||||
/* If no protocol prefix was detected, we can use the shortened
|
||||
* filename as-is */
|
||||
@ -3977,7 +3978,7 @@ static int bdrv_reopen_parse_backing(BDRVReopenState *reopen_state,
|
||||
new_backing_bs = NULL;
|
||||
break;
|
||||
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);
|
||||
if (new_backing_bs == NULL) {
|
||||
return -EINVAL;
|
||||
@ -4240,8 +4241,8 @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
|
||||
}
|
||||
|
||||
if (child) {
|
||||
const char *str = qobject_get_try_str(new);
|
||||
if (!strcmp(child->bs->node_name, str)) {
|
||||
if (!strcmp(child->bs->node_name,
|
||||
qstring_get_str(qobject_to(QString, new)))) {
|
||||
continue; /* Found child with this name, skip option */
|
||||
}
|
||||
}
|
||||
@ -6938,13 +6939,13 @@ void bdrv_refresh_filename(BlockDriverState *bs)
|
||||
if (bs->exact_filename[0]) {
|
||||
pstrcpy(bs->filename, sizeof(bs->filename), bs->exact_filename);
|
||||
} 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",
|
||||
qstring_get_str(json)) >= sizeof(bs->filename)) {
|
||||
json->str) >= sizeof(bs->filename)) {
|
||||
/* Give user a hint if we truncated things. */
|
||||
strcpy(bs->filename + sizeof(bs->filename) - 4, "...");
|
||||
}
|
||||
qobject_unref(json);
|
||||
g_string_free(json, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -359,8 +359,8 @@ static int qemu_gluster_parse_uri(BlockdevOptionsGluster *gconf,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
gconf->server = g_new0(SocketAddressList, 1);
|
||||
gconf->server->value = gsconf = g_new0(SocketAddress, 1);
|
||||
gsconf = g_new0(SocketAddress, 1);
|
||||
QAPI_LIST_PREPEND(gconf->server, gsconf);
|
||||
|
||||
/* transport */
|
||||
if (!uri->scheme || !strcmp(uri->scheme, "gluster")) {
|
||||
|
@ -486,12 +486,7 @@ static void bdrv_query_blk_stats(BlockDeviceStats *ds, BlockBackend *blk)
|
||||
ds->account_failed = stats->account_failed;
|
||||
|
||||
while ((ts = block_acct_interval_next(stats, ts))) {
|
||||
BlockDeviceTimedStatsList *timed_stats =
|
||||
g_malloc0(sizeof(*timed_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 *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);
|
||||
dev_stats->avg_wr_queue_depth =
|
||||
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],
|
||||
|
@ -232,7 +232,7 @@ static void qemu_rbd_parse_filename(const char *filename, QDict *options,
|
||||
|
||||
if (keypairs) {
|
||||
qdict_put(options, "=keyvalue-pairs",
|
||||
qobject_to_json(QOBJECT(keypairs)));
|
||||
qstring_from_gstring(qobject_to_json(QOBJECT(keypairs))));
|
||||
}
|
||||
|
||||
done:
|
||||
|
@ -776,15 +776,13 @@ static int qmp_query_chardev_foreach(Object *obj, void *data)
|
||||
{
|
||||
Chardev *chr = CHARDEV(obj);
|
||||
ChardevInfoList **list = data;
|
||||
ChardevInfoList *info = g_malloc0(sizeof(*info));
|
||||
ChardevInfo *value = g_malloc0(sizeof(*value));
|
||||
|
||||
info->value = g_malloc0(sizeof(*info->value));
|
||||
info->value->label = g_strdup(chr->label);
|
||||
info->value->filename = g_strdup(chr->filename);
|
||||
info->value->frontend_open = chr->be && chr->be->fe_open;
|
||||
value->label = g_strdup(chr->label);
|
||||
value->filename = g_strdup(chr->filename);
|
||||
value->frontend_open = chr->be && chr->be->fe_open;
|
||||
|
||||
info->next = *list;
|
||||
*list = info;
|
||||
QAPI_LIST_PREPEND(*list, value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -803,12 +801,10 @@ static void
|
||||
qmp_prepend_backend(const char *name, void *opaque)
|
||||
{
|
||||
ChardevBackendInfoList **list = opaque;
|
||||
ChardevBackendInfoList *info = g_malloc0(sizeof(*info));
|
||||
ChardevBackendInfo *value = g_new0(ChardevBackendInfo, 1);
|
||||
|
||||
info->value = g_malloc0(sizeof(*info->value));
|
||||
info->value->name = g_strdup(name);
|
||||
info->next = *list;
|
||||
*list = info;
|
||||
value->name = g_strdup(name);
|
||||
QAPI_LIST_PREPEND(*list, value);
|
||||
}
|
||||
|
||||
ChardevBackendInfoList *qmp_query_chardev_backends(Error **errp)
|
||||
|
@ -531,15 +531,11 @@ TimerAlarmMethodList *qmp_query_alarm_methods(Error **errp)
|
||||
bool current = true;
|
||||
|
||||
for (p = alarm_timers; p->name; p++) {
|
||||
TimerAlarmMethodList *info = g_malloc0(sizeof(*info));
|
||||
info->value = g_malloc0(sizeof(*info->value));
|
||||
info->value->method_name = g_strdup(p->name);
|
||||
info->value->current = current;
|
||||
|
||||
TimerAlarmMethod *value = g_malloc0(*value);
|
||||
value->method_name = g_strdup(p->name);
|
||||
value->current = current;
|
||||
QAPI_LIST_PREPEND(method_list, value);
|
||||
current = false;
|
||||
|
||||
info->next = method_list;
|
||||
method_list = info;
|
||||
}
|
||||
|
||||
return method_list;
|
||||
|
@ -215,7 +215,6 @@ MachineInfoList *qmp_query_machines(Error **errp)
|
||||
|
||||
for (el = machines; el; el = el->next) {
|
||||
MachineClass *mc = el->data;
|
||||
MachineInfoList *entry;
|
||||
MachineInfo *info;
|
||||
|
||||
info = g_malloc0(sizeof(*info));
|
||||
@ -243,10 +242,7 @@ MachineInfoList *qmp_query_machines(Error **errp)
|
||||
info->has_default_ram_id = true;
|
||||
}
|
||||
|
||||
entry = g_malloc0(sizeof(*entry));
|
||||
entry->value = info;
|
||||
entry->next = mach_list;
|
||||
mach_list = entry;
|
||||
QAPI_LIST_PREPEND(mach_list, info);
|
||||
}
|
||||
|
||||
g_slist_free(machines);
|
||||
|
@ -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)
|
||||
{
|
||||
strList *item = g_new0(strList, 1);
|
||||
|
||||
item->value = g_strdup(type);
|
||||
item->next = mc->allowed_dynamic_sysbus_devices;
|
||||
mc->allowed_dynamic_sysbus_devices = item;
|
||||
QAPI_LIST_PREPEND(mc->allowed_dynamic_sysbus_devices, g_strdup(type));
|
||||
}
|
||||
|
||||
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++) {
|
||||
Object *cpu;
|
||||
HotpluggableCPUList *list_item = g_new0(typeof(*list_item), 1);
|
||||
HotpluggableCPU *cpu_item = g_new0(typeof(*cpu_item), 1);
|
||||
|
||||
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->qom_path = object_get_canonical_path(cpu);
|
||||
}
|
||||
list_item->value = cpu_item;
|
||||
list_item->next = head;
|
||||
head = list_item;
|
||||
QAPI_LIST_PREPEND(head, cpu_item);
|
||||
}
|
||||
return head;
|
||||
}
|
||||
|
@ -970,7 +970,7 @@ static const VMStateDescription vmstate_virtio_gpu_scanouts = {
|
||||
};
|
||||
|
||||
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;
|
||||
struct virtio_gpu_simple_resource *res;
|
||||
|
@ -386,7 +386,7 @@ static void kvm_s390_release_adapter_routes(S390FLICState *fs,
|
||||
* reached
|
||||
*/
|
||||
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;
|
||||
int len = FLIC_SAVE_INITIAL_SIZE;
|
||||
|
@ -127,13 +127,7 @@ RockerPortList *qmp_query_rocker_ports(const char *name, Error **errp)
|
||||
}
|
||||
|
||||
for (i = r->fp_ports - 1; i >= 0; i--) {
|
||||
RockerPortList *info = g_malloc0(sizeof(*info));
|
||||
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;
|
||||
QAPI_LIST_PREPEND(list, fp_port_get_info(r->fp_port[i]));
|
||||
}
|
||||
|
||||
return list;
|
||||
|
@ -51,14 +51,17 @@ bool fp_port_get_link_up(FpPort *port)
|
||||
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);
|
||||
info->value->enabled = port->enabled;
|
||||
info->value->link_up = fp_port_get_link_up(port);
|
||||
info->value->speed = port->speed;
|
||||
info->value->duplex = port->duplex;
|
||||
info->value->autoneg = port->autoneg;
|
||||
RockerPort *value = g_malloc0(sizeof(*value));
|
||||
|
||||
value->name = g_strdup(port->name);
|
||||
value->enabled = port->enabled;
|
||||
value->link_up = fp_port_get_link_up(port);
|
||||
value->speed = port->speed;
|
||||
value->duplex = port->duplex;
|
||||
value->autoneg = port->autoneg;
|
||||
return value;
|
||||
}
|
||||
|
||||
void fp_port_get_macaddr(FpPort *port, MACAddr *macaddr)
|
||||
|
@ -28,7 +28,7 @@ int fp_port_eg(FpPort *port, const struct iovec *iov, int iovcnt);
|
||||
|
||||
char *fp_port_get_name(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_set_macaddr(FpPort *port, MACAddr *macaddr);
|
||||
uint8_t fp_port_get_learning(FpPort *port);
|
||||
|
@ -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 *mask = &flow->mask;
|
||||
struct of_dpa_flow_fill_context *flow_context = user_data;
|
||||
RockerOfDpaFlowList *new;
|
||||
RockerOfDpaFlow *nflow;
|
||||
RockerOfDpaFlowKey *nkey;
|
||||
RockerOfDpaFlowMask *nmask;
|
||||
@ -2307,8 +2306,7 @@ static void of_dpa_flow_fill(void *cookie, void *value, void *user_data)
|
||||
return;
|
||||
}
|
||||
|
||||
new = g_malloc0(sizeof(*new));
|
||||
nflow = new->value = g_malloc0(sizeof(*nflow));
|
||||
nflow = g_malloc0(sizeof(*nflow));
|
||||
nkey = nflow->key = g_malloc0(sizeof(*nkey));
|
||||
nmask = nflow->mask = g_malloc0(sizeof(*nmask));
|
||||
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;
|
||||
}
|
||||
|
||||
new->next = flow_context->list;
|
||||
flow_context->list = new;
|
||||
QAPI_LIST_PREPEND(flow_context->list, nflow);
|
||||
}
|
||||
|
||||
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_fill_context *flow_context = user_data;
|
||||
RockerOfDpaGroupList *new;
|
||||
RockerOfDpaGroup *ngroup;
|
||||
struct uint32List *id;
|
||||
int i;
|
||||
|
||||
if (flow_context->type != 9 &&
|
||||
@ -2479,8 +2474,7 @@ static void of_dpa_group_fill(void *key, void *value, void *user_data)
|
||||
return;
|
||||
}
|
||||
|
||||
new = g_malloc0(sizeof(*new));
|
||||
ngroup = new->value = g_malloc0(sizeof(*ngroup));
|
||||
ngroup = g_malloc0(sizeof(*ngroup));
|
||||
|
||||
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);
|
||||
for (i = 0; i < group->l2_flood.group_count; i++) {
|
||||
ngroup->has_group_ids = true;
|
||||
id = g_malloc0(sizeof(*id));
|
||||
id->value = group->l2_flood.group_ids[i];
|
||||
id->next = ngroup->group_ids;
|
||||
ngroup->group_ids = id;
|
||||
QAPI_LIST_PREPEND(ngroup->group_ids, group->l2_flood.group_ids[i]);
|
||||
}
|
||||
break;
|
||||
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;
|
||||
}
|
||||
|
||||
new->next = flow_context->list;
|
||||
flow_context->list = new;
|
||||
QAPI_LIST_PREPEND(flow_context->list, ngroup);
|
||||
}
|
||||
|
||||
RockerOfDpaGroupList *qmp_query_rocker_of_dpa_groups(const char *name,
|
||||
|
@ -437,17 +437,14 @@ static void rxfilter_notify(NetClientState *nc)
|
||||
|
||||
static intList *get_vlan_table(VirtIONet *n)
|
||||
{
|
||||
intList *list, *entry;
|
||||
intList *list;
|
||||
int i, j;
|
||||
|
||||
list = NULL;
|
||||
for (i = 0; i < MAX_VLAN >> 5; i++) {
|
||||
for (j = 0; n->vlans[i] && j <= 0x1f; j++) {
|
||||
if (n->vlans[i] & (1U << j)) {
|
||||
entry = g_malloc0(sizeof(*entry));
|
||||
entry->value = (i << 5) + j;
|
||||
entry->next = list;
|
||||
list = entry;
|
||||
QAPI_LIST_PREPEND(list, (i << 5) + j);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -460,7 +457,7 @@ static RxFilterInfo *virtio_net_query_rxfilter(NetClientState *nc)
|
||||
VirtIONet *n = qemu_get_nic_opaque(nc);
|
||||
VirtIODevice *vdev = VIRTIO_DEVICE(n);
|
||||
RxFilterInfo *info;
|
||||
strList *str_list, *entry;
|
||||
strList *str_list;
|
||||
int i;
|
||||
|
||||
info = g_malloc0(sizeof(*info));
|
||||
@ -491,19 +488,15 @@ static RxFilterInfo *virtio_net_query_rxfilter(NetClientState *nc)
|
||||
|
||||
str_list = NULL;
|
||||
for (i = 0; i < n->mac_table.first_multi; i++) {
|
||||
entry = g_malloc0(sizeof(*entry));
|
||||
entry->value = qemu_mac_strdup_printf(n->mac_table.macs + i * ETH_ALEN);
|
||||
entry->next = str_list;
|
||||
str_list = entry;
|
||||
QAPI_LIST_PREPEND(str_list,
|
||||
qemu_mac_strdup_printf(n->mac_table.macs + i * ETH_ALEN));
|
||||
}
|
||||
info->unicast_table = str_list;
|
||||
|
||||
str_list = NULL;
|
||||
for (i = n->mac_table.first_multi; i < n->mac_table.in_use; i++) {
|
||||
entry = g_malloc0(sizeof(*entry));
|
||||
entry->value = qemu_mac_strdup_printf(n->mac_table.macs + i * ETH_ALEN);
|
||||
entry->next = str_list;
|
||||
str_list = entry;
|
||||
QAPI_LIST_PREPEND(str_list,
|
||||
qemu_mac_strdup_printf(n->mac_table.macs + i * ETH_ALEN));
|
||||
}
|
||||
info->multicast_table = str_list;
|
||||
info->vlan_table = get_vlan_table(n);
|
||||
|
@ -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,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, JSONWriter *vmdesc)
|
||||
{
|
||||
fprintf(stderr, "uint16_from_uint8 is used only for backwards compatibility.\n");
|
||||
fprintf(stderr, "Never should be used to write a new state.\n");
|
||||
|
@ -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,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, JSONWriter *vmdesc)
|
||||
{
|
||||
fprintf(stderr, "uint32_as_uint16 is only used for backward compatibility.\n");
|
||||
fprintf(stderr, "This functions shouldn't be called.\n");
|
||||
|
@ -634,7 +634,7 @@ void msix_unset_vector_notifiers(PCIDevice *dev)
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
|
@ -559,7 +559,7 @@ static int get_pci_config_device(QEMUFile *f, void *pv, size_t size,
|
||||
|
||||
/* just put buffer */
|
||||
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;
|
||||
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,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, JSONWriter *vmdesc)
|
||||
{
|
||||
int i;
|
||||
PCIDevice *s = container_of(pv, PCIDevice, irq_state);
|
||||
|
@ -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,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, JSONWriter *vmdesc)
|
||||
{
|
||||
PCIDevice *d = container_of(pv, PCIDevice, shpc);
|
||||
qemu_put_buffer(f, d->shpc->config, SHPC_SIZEOF(d));
|
||||
|
@ -78,7 +78,7 @@ static void clean_recv_mads(RdmaBackendDev *backend_dev)
|
||||
unsigned long cqe_ctx_id;
|
||||
|
||||
do {
|
||||
cqe_ctx_id = rdma_protected_qlist_pop_int64(&backend_dev->
|
||||
cqe_ctx_id = rdma_protected_gqueue_pop_int64(&backend_dev->
|
||||
recv_mads_list);
|
||||
if (cqe_ctx_id != -ENOENT) {
|
||||
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->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;
|
||||
}
|
||||
@ -1111,7 +1111,7 @@ static void process_incoming_mad_req(RdmaBackendDev *backend_dev,
|
||||
|
||||
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) {
|
||||
rdma_warn_report("No more free MADs buffers, waiting for a while");
|
||||
sleep(THR_POLL_TO);
|
||||
@ -1185,7 +1185,7 @@ static int mad_init(RdmaBackendDev *backend_dev, CharBackend *mad_chr_be)
|
||||
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);
|
||||
|
||||
@ -1205,7 +1205,7 @@ static void mad_fini(RdmaBackendDev *backend_dev)
|
||||
{
|
||||
disable_rdmacm_mux_async(backend_dev);
|
||||
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,
|
||||
|
@ -43,7 +43,7 @@ typedef struct RdmaBackendDev {
|
||||
struct ibv_context *context;
|
||||
struct ibv_comp_channel *channel;
|
||||
uint8_t port_num;
|
||||
RdmaProtectedQList recv_mads_list;
|
||||
RdmaProtectedGQueue recv_mads_list;
|
||||
RdmaCmMux rdmacm_mux;
|
||||
} RdmaBackendDev;
|
||||
|
||||
|
@ -14,8 +14,6 @@
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/qmp/qlist.h"
|
||||
#include "qapi/qmp/qnum.h"
|
||||
#include "trace.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);
|
||||
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) {
|
||||
qlist_destroy_obj(QOBJECT(list->list));
|
||||
g_queue_free_full(list->list, g_free);
|
||||
qemu_mutex_destroy(&list->lock);
|
||||
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);
|
||||
qlist_append_int(list->list, value);
|
||||
g_queue_push_tail(list->list, g_memdup(&value, sizeof(value)));
|
||||
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);
|
||||
obj = qlist_pop(list->list);
|
||||
|
||||
valp = g_queue_pop_head(list->list);
|
||||
qemu_mutex_unlock(&list->lock);
|
||||
|
||||
if (!obj) {
|
||||
if (!valp) {
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
return qnum_get_uint(qobject_to(QNum, obj));
|
||||
val = *valp;
|
||||
g_free(valp);
|
||||
return val;
|
||||
}
|
||||
|
||||
void rdma_protected_gslist_init(RdmaProtectedGSList *list)
|
||||
|
@ -28,10 +28,10 @@
|
||||
#define rdma_info_report(fmt, ...) \
|
||||
info_report("%s: " fmt, "rdma", ## __VA_ARGS__)
|
||||
|
||||
typedef struct RdmaProtectedQList {
|
||||
typedef struct RdmaProtectedGQueue {
|
||||
QemuMutex lock;
|
||||
QList *list;
|
||||
} RdmaProtectedQList;
|
||||
GQueue *list;
|
||||
} RdmaProtectedGQueue;
|
||||
|
||||
typedef struct RdmaProtectedGSList {
|
||||
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_unmap(PCIDevice *dev, void *buffer, dma_addr_t len);
|
||||
void rdma_protected_qlist_init(RdmaProtectedQList *list);
|
||||
void rdma_protected_qlist_destroy(RdmaProtectedQList *list);
|
||||
void rdma_protected_qlist_append_int64(RdmaProtectedQList *list, int64_t value);
|
||||
int64_t rdma_protected_qlist_pop_int64(RdmaProtectedQList *list);
|
||||
void rdma_protected_gqueue_init(RdmaProtectedGQueue *list);
|
||||
void rdma_protected_gqueue_destroy(RdmaProtectedGQueue *list);
|
||||
void rdma_protected_gqueue_append_int64(RdmaProtectedGQueue *list,
|
||||
int64_t value);
|
||||
int64_t rdma_protected_gqueue_pop_int64(RdmaProtectedGQueue *list);
|
||||
void rdma_protected_gslist_init(RdmaProtectedGSList *list);
|
||||
void rdma_protected_gslist_destroy(RdmaProtectedGSList *list);
|
||||
void rdma_protected_gslist_append_int32(RdmaProtectedGSList *list,
|
||||
|
@ -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,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, JSONWriter *vmdesc)
|
||||
{
|
||||
int *v = pv;
|
||||
qemu_put_be16(f, *v);
|
||||
|
@ -1638,7 +1638,7 @@ static char *scsibus_get_fw_dev_path(DeviceState *dev)
|
||||
/* SCSI request list. For simplicity, pv points to the whole device */
|
||||
|
||||
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;
|
||||
SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, s->qdev.parent_bus);
|
||||
|
@ -2227,7 +2227,7 @@ static int usbredir_post_load(void *priv, int version_id)
|
||||
|
||||
/* For usbredirparser migration */
|
||||
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;
|
||||
uint8_t *data;
|
||||
@ -2294,7 +2294,7 @@ static const VMStateInfo usbredir_parser_vmstate_info = {
|
||||
|
||||
/* For buffered packets (iso/irq) queue migration */
|
||||
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;
|
||||
USBRedirDevice *dev = endp->dev;
|
||||
@ -2421,7 +2421,8 @@ static const VMStateDescription usbredir_ep_vmstate = {
|
||||
|
||||
/* For PacketIdQueue migration */
|
||||
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;
|
||||
USBRedirDevice *dev = q->dev;
|
||||
|
@ -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,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, JSONWriter *vmdesc)
|
||||
{
|
||||
VirtIODevice *vdev = pv;
|
||||
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 */
|
||||
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);
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ struct VMStateInfo {
|
||||
const char *name;
|
||||
int (*get)(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 {
|
||||
@ -1169,9 +1169,10 @@ extern const VMStateInfo vmstate_info_qlist;
|
||||
int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
|
||||
void *opaque, int version_id);
|
||||
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,
|
||||
void *opaque, QJSON *vmdesc, int version_id);
|
||||
void *opaque, JSONWriter *vmdesc,
|
||||
int version_id);
|
||||
|
||||
bool vmstate_save_needed(const VMStateDescription *vmsd, void *opaque);
|
||||
|
||||
|
35
include/qapi/qmp/json-writer.h
Normal file
35
include/qapi/qmp/json-writer.h
Normal 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
|
@ -23,7 +23,5 @@ struct QBool {
|
||||
|
||||
QBool *qbool_from_bool(bool value);
|
||||
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 */
|
||||
|
@ -39,10 +39,8 @@ void qdict_put_obj(QDict *qdict, const char *key, QObject *value);
|
||||
void qdict_del(QDict *qdict, const char *key);
|
||||
int qdict_haskey(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_next(const QDict *qdict, const QDictEntry *entry);
|
||||
void qdict_destroy_obj(QObject *obj);
|
||||
|
||||
/* Helper to qdict_put_obj(), accepts any object */
|
||||
#define qdict_put(qdict, key, obj) \
|
||||
|
@ -25,7 +25,7 @@ QDict *qdict_from_vjsonf_nofail(const char *string, va_list ap)
|
||||
QDict *qdict_from_jsonf_nofail(const char *string, ...)
|
||||
GCC_FMT_ATTR(1, 2);
|
||||
|
||||
QString *qobject_to_json(const QObject *obj);
|
||||
QString *qobject_to_json_pretty(const QObject *obj);
|
||||
GString *qobject_to_json(const QObject *obj);
|
||||
GString *qobject_to_json_pretty(const QObject *obj, bool pretty);
|
||||
|
||||
#endif /* QJSON_H */
|
||||
|
@ -51,8 +51,6 @@ QObject *qlist_pop(QList *qlist);
|
||||
QObject *qlist_peek(QList *qlist);
|
||||
int qlist_empty(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)
|
||||
{
|
||||
|
@ -26,6 +26,4 @@ static inline QNull *qnull(void)
|
||||
return qobject_ref(&qnull_);
|
||||
}
|
||||
|
||||
bool qnull_is_equal(const QObject *x, const QObject *y);
|
||||
|
||||
#endif /* QNULL_H */
|
||||
|
@ -68,7 +68,4 @@ double qnum_get_double(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 */
|
||||
|
@ -64,14 +64,6 @@ QEMU_BUILD_BUG_MSG(QTYPE__MAX != 7,
|
||||
#define qobject_to(type, obj) \
|
||||
((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)
|
||||
{
|
||||
if (obj) {
|
||||
@ -90,6 +82,7 @@ bool qobject_is_equal(const QObject *x, const QObject *y);
|
||||
|
||||
/**
|
||||
* qobject_destroy(): Free resources used by the object
|
||||
* For use via qobject_unref() only!
|
||||
*/
|
||||
void qobject_destroy(QObject *obj);
|
||||
|
||||
|
@ -17,23 +17,13 @@
|
||||
|
||||
struct QString {
|
||||
struct QObjectBase_ base;
|
||||
char *string;
|
||||
size_t length;
|
||||
size_t capacity;
|
||||
const char *string;
|
||||
};
|
||||
|
||||
QString *qstring_new(void);
|
||||
QString *qstring_from_str(const char *str);
|
||||
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_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 */
|
||||
|
@ -57,8 +57,8 @@ typedef struct IOMMUMemoryRegion IOMMUMemoryRegion;
|
||||
typedef struct ISABus ISABus;
|
||||
typedef struct ISADevice ISADevice;
|
||||
typedef struct IsaDma IsaDma;
|
||||
typedef struct JSONWriter JSONWriter;
|
||||
typedef struct MACAddr MACAddr;
|
||||
typedef struct ReservedRegion ReservedRegion;
|
||||
typedef struct MachineClass MachineClass;
|
||||
typedef struct MachineState MachineState;
|
||||
typedef struct MemoryListener MemoryListener;
|
||||
@ -107,7 +107,6 @@ typedef struct QEMUSGList QEMUSGList;
|
||||
typedef struct QemuSpin QemuSpin;
|
||||
typedef struct QEMUTimer QEMUTimer;
|
||||
typedef struct QEMUTimerListGroup QEMUTimerListGroup;
|
||||
typedef struct QJSON QJSON;
|
||||
typedef struct QList QList;
|
||||
typedef struct QNull QNull;
|
||||
typedef struct QNum QNum;
|
||||
@ -115,6 +114,7 @@ typedef struct QObject QObject;
|
||||
typedef struct QString QString;
|
||||
typedef struct RAMBlock RAMBlock;
|
||||
typedef struct Range Range;
|
||||
typedef struct ReservedRegion ReservedRegion;
|
||||
typedef struct SavedIOTLB SavedIOTLB;
|
||||
typedef struct SHPCDevice SHPCDevice;
|
||||
typedef struct SSIBus SSIBus;
|
||||
|
@ -6,7 +6,6 @@ migration_files = files(
|
||||
'vmstate.c',
|
||||
'qemu-file-channel.c',
|
||||
'qemu-file.c',
|
||||
'qjson.c',
|
||||
)
|
||||
softmmu_ss.add(migration_files)
|
||||
|
||||
|
@ -406,12 +406,9 @@ int migration_incoming_enable_colo(void)
|
||||
void migrate_add_address(SocketAddress *address)
|
||||
{
|
||||
MigrationIncomingState *mis = migration_incoming_get_current();
|
||||
SocketAddressList *addrs;
|
||||
|
||||
addrs = g_new0(SocketAddressList, 1);
|
||||
addrs->next = mis->socket_address_list;
|
||||
mis->socket_address_list = addrs;
|
||||
addrs->value = QAPI_CLONE(SocketAddress, address);
|
||||
QAPI_LIST_PREPEND(mis->socket_address_list,
|
||||
QAPI_CLONE(SocketAddress, address));
|
||||
}
|
||||
|
||||
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(
|
||||
MigrationCapabilityStatusList *list,
|
||||
MigrationCapability index,
|
||||
bool state)
|
||||
static MigrationCapabilityStatus *migrate_cap_add(MigrationCapability index,
|
||||
bool state)
|
||||
{
|
||||
MigrationCapabilityStatusList *cap;
|
||||
MigrationCapabilityStatus *cap;
|
||||
|
||||
cap = g_new0(MigrationCapabilityStatusList, 1);
|
||||
cap->value = g_new0(MigrationCapabilityStatus, 1);
|
||||
cap->value->capability = index;
|
||||
cap->value->state = state;
|
||||
cap->next = list;
|
||||
cap = g_new0(MigrationCapabilityStatus, 1);
|
||||
cap->capability = index;
|
||||
cap->state = state;
|
||||
|
||||
return cap;
|
||||
}
|
||||
|
||||
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);
|
||||
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++) {
|
||||
if (ms->enabled_capabilities[i]) {
|
||||
head = migrate_cap_add(head, i, true);
|
||||
QAPI_LIST_PREPEND(head, migrate_cap_add(i, true));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -145,14 +145,11 @@ static struct PostcopyBlocktimeContext *blocktime_context_new(void)
|
||||
static uint32List *get_vcpu_blocktime_list(PostcopyBlocktimeContext *ctx)
|
||||
{
|
||||
MachineState *ms = MACHINE(qdev_get_machine());
|
||||
uint32List *list = NULL, *entry = NULL;
|
||||
uint32List *list = NULL;
|
||||
int i;
|
||||
|
||||
for (i = ms->smp.cpus - 1; i >= 0; i--) {
|
||||
entry = g_new0(uint32List, 1);
|
||||
entry->value = ctx->vcpu_blocktime[i];
|
||||
entry->next = list;
|
||||
list = entry;
|
||||
QAPI_LIST_PREPEND(list, ctx->vcpu_blocktime[i]);
|
||||
}
|
||||
|
||||
return list;
|
||||
|
@ -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);
|
||||
}
|
@ -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 */
|
@ -42,6 +42,7 @@
|
||||
#include "postcopy-ram.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/qapi-commands-migration.h"
|
||||
#include "qapi/qmp/json-writer.h"
|
||||
#include "qapi/qmp/qerror.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "sysemu/cpus.h"
|
||||
@ -58,7 +59,6 @@
|
||||
#include "sysemu/runstate.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "sysemu/xen.h"
|
||||
#include "qjson.h"
|
||||
#include "migration/colo.h"
|
||||
#include "qemu/bitmap.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,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, JSONWriter *vmdesc)
|
||||
{
|
||||
QEMUTimer *v = pv;
|
||||
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,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, JSONWriter *vmdesc)
|
||||
{
|
||||
MigrationCapability *capability = pv;
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
@ -893,18 +894,19 @@ static void vmstate_save_old_style(QEMUFile *f, SaveStateEntry *se, QJSON *vmdes
|
||||
size = qemu_ftell_fast(f) - old_offset;
|
||||
|
||||
if (vmdesc) {
|
||||
json_prop_int(vmdesc, "size", size);
|
||||
json_start_array(vmdesc, "fields");
|
||||
json_start_object(vmdesc, NULL);
|
||||
json_prop_str(vmdesc, "name", "data");
|
||||
json_prop_int(vmdesc, "size", size);
|
||||
json_prop_str(vmdesc, "type", "buffer");
|
||||
json_end_object(vmdesc);
|
||||
json_end_array(vmdesc);
|
||||
json_writer_int64(vmdesc, "size", size);
|
||||
json_writer_start_array(vmdesc, "fields");
|
||||
json_writer_start_object(vmdesc, NULL);
|
||||
json_writer_str(vmdesc, "name", "data");
|
||||
json_writer_int64(vmdesc, "size", size);
|
||||
json_writer_str(vmdesc, "type", "buffer");
|
||||
json_writer_end_object(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)");
|
||||
if (!se->vmsd) {
|
||||
@ -1357,14 +1359,15 @@ int qemu_savevm_state_complete_precopy_non_iterable(QEMUFile *f,
|
||||
bool in_postcopy,
|
||||
bool inactivate_disks)
|
||||
{
|
||||
g_autoptr(QJSON) vmdesc = NULL;
|
||||
g_autoptr(JSONWriter) vmdesc = NULL;
|
||||
int vmdesc_len;
|
||||
SaveStateEntry *se;
|
||||
int ret;
|
||||
|
||||
vmdesc = qjson_new();
|
||||
json_prop_int(vmdesc, "page_size", qemu_target_page_size());
|
||||
json_start_array(vmdesc, "devices");
|
||||
vmdesc = json_writer_new(false);
|
||||
json_writer_start_object(vmdesc, NULL);
|
||||
json_writer_int64(vmdesc, "page_size", qemu_target_page_size());
|
||||
json_writer_start_array(vmdesc, "devices");
|
||||
QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
|
||||
|
||||
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);
|
||||
|
||||
json_start_object(vmdesc, NULL);
|
||||
json_prop_str(vmdesc, "name", se->idstr);
|
||||
json_prop_int(vmdesc, "instance_id", se->instance_id);
|
||||
json_writer_start_object(vmdesc, NULL);
|
||||
json_writer_str(vmdesc, "name", se->idstr);
|
||||
json_writer_int64(vmdesc, "instance_id", se->instance_id);
|
||||
|
||||
save_section_header(f, se, QEMU_VM_SECTION_FULL);
|
||||
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);
|
||||
save_section_footer(f, se);
|
||||
|
||||
json_end_object(vmdesc);
|
||||
json_writer_end_object(vmdesc);
|
||||
}
|
||||
|
||||
if (inactivate_disks) {
|
||||
@ -1409,14 +1412,14 @@ int qemu_savevm_state_complete_precopy_non_iterable(QEMUFile *f,
|
||||
qemu_put_byte(f, QEMU_VM_EOF);
|
||||
}
|
||||
|
||||
json_end_array(vmdesc);
|
||||
qjson_finish(vmdesc);
|
||||
vmdesc_len = strlen(qjson_get_str(vmdesc));
|
||||
json_writer_end_array(vmdesc);
|
||||
json_writer_end_object(vmdesc);
|
||||
vmdesc_len = strlen(json_writer_get(vmdesc));
|
||||
|
||||
if (should_send_vmdesc()) {
|
||||
qemu_put_byte(f, QEMU_VM_VMDESCRIPTION);
|
||||
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;
|
||||
|
@ -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,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, JSONWriter *vmdesc)
|
||||
{
|
||||
bool *v = pv;
|
||||
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,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, JSONWriter *vmdesc)
|
||||
{
|
||||
int8_t *v = pv;
|
||||
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,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, JSONWriter *vmdesc)
|
||||
{
|
||||
int16_t *v = pv;
|
||||
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,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, JSONWriter *vmdesc)
|
||||
{
|
||||
int32_t *v = pv;
|
||||
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,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, JSONWriter *vmdesc)
|
||||
{
|
||||
int64_t *v = pv;
|
||||
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,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, JSONWriter *vmdesc)
|
||||
{
|
||||
uint8_t *v = pv;
|
||||
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,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, JSONWriter *vmdesc)
|
||||
{
|
||||
uint16_t *v = pv;
|
||||
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,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, JSONWriter *vmdesc)
|
||||
{
|
||||
uint32_t *v = pv;
|
||||
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,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, JSONWriter *vmdesc)
|
||||
{
|
||||
uint64_t *v = pv;
|
||||
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,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, JSONWriter *vmdesc)
|
||||
|
||||
{
|
||||
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,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, JSONWriter *vmdesc)
|
||||
{
|
||||
CPU_DoubleU *v = pv;
|
||||
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,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, JSONWriter *vmdesc)
|
||||
{
|
||||
uint8_t *v = pv;
|
||||
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,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, JSONWriter *vmdesc)
|
||||
{
|
||||
static const uint8_t buf[1024];
|
||||
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,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, JSONWriter *vmdesc)
|
||||
{
|
||||
const VMStateDescription *vmsd = field->vmsd;
|
||||
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,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, JSONWriter *vmdesc)
|
||||
{
|
||||
unsigned long *bmp = pv;
|
||||
int i, idx = 0;
|
||||
@ -637,7 +637,7 @@ static int get_qtailq(QEMUFile *f, void *pv, size_t unused_size,
|
||||
|
||||
/* put for QTAILQ */
|
||||
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;
|
||||
/* offset of the QTAILQ entry in a QTAILQ element*/
|
||||
@ -670,7 +670,7 @@ struct put_gtree_data {
|
||||
QEMUFile *f;
|
||||
const VMStateDescription *key_vmsd;
|
||||
const VMStateDescription *val_vmsd;
|
||||
QJSON *vmdesc;
|
||||
JSONWriter *vmdesc;
|
||||
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,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, JSONWriter *vmdesc)
|
||||
{
|
||||
bool direct_key = (!field->start);
|
||||
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,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, JSONWriter *vmdesc)
|
||||
{
|
||||
const VMStateDescription *vmsd = field->vmsd;
|
||||
/* offset of the QTAILQ entry in a QTAILQ element*/
|
||||
|
@ -14,14 +14,14 @@
|
||||
#include "migration.h"
|
||||
#include "migration/vmstate.h"
|
||||
#include "savevm.h"
|
||||
#include "qapi/qmp/json-writer.h"
|
||||
#include "qemu-file.h"
|
||||
#include "qemu/bitops.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "trace.h"
|
||||
#include "qjson.h"
|
||||
|
||||
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,
|
||||
void *opaque);
|
||||
|
||||
@ -249,7 +249,8 @@ static bool vmsd_can_compress(const VMStateField *field)
|
||||
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)
|
||||
{
|
||||
char *name, *old_name;
|
||||
@ -270,25 +271,26 @@ static void vmsd_desc_field_start(const VMStateDescription *vmsd, QJSON *vmdesc,
|
||||
g_free(old_name);
|
||||
}
|
||||
|
||||
json_start_object(vmdesc, NULL);
|
||||
json_prop_str(vmdesc, "name", name);
|
||||
json_writer_start_object(vmdesc, NULL);
|
||||
json_writer_str(vmdesc, "name", name);
|
||||
if (is_array) {
|
||||
if (can_compress) {
|
||||
json_prop_int(vmdesc, "array_len", max);
|
||||
json_writer_int64(vmdesc, "array_len", max);
|
||||
} 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) {
|
||||
json_start_object(vmdesc, "struct");
|
||||
json_writer_start_object(vmdesc, "struct");
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if (!vmdesc) {
|
||||
@ -297,11 +299,11 @@ static void vmsd_desc_field_end(const VMStateDescription *vmsd, QJSON *vmdesc,
|
||||
|
||||
if (field->flags & VMS_STRUCT) {
|
||||
/* 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_end_object(vmdesc);
|
||||
json_writer_int64(vmdesc, "size", size);
|
||||
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,
|
||||
void *opaque, QJSON *vmdesc_id)
|
||||
void *opaque, JSONWriter *vmdesc_id)
|
||||
{
|
||||
return vmstate_save_state_v(f, vmsd, opaque, vmdesc_id, vmsd->version_id);
|
||||
}
|
||||
|
||||
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;
|
||||
const VMStateField *field = vmsd->fields;
|
||||
@ -339,9 +341,9 @@ int vmstate_save_state_v(QEMUFile *f, const VMStateDescription *vmsd,
|
||||
}
|
||||
|
||||
if (vmdesc) {
|
||||
json_prop_str(vmdesc, "vmsd_name", vmsd->name);
|
||||
json_prop_int(vmdesc, "version", version_id);
|
||||
json_start_array(vmdesc, "fields");
|
||||
json_writer_str(vmdesc, "vmsd_name", vmsd->name);
|
||||
json_writer_int64(vmdesc, "version", version_id);
|
||||
json_writer_start_array(vmdesc, "fields");
|
||||
}
|
||||
|
||||
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 size = vmstate_size(opaque, field);
|
||||
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);
|
||||
if (field->flags & VMS_POINTER) {
|
||||
@ -413,7 +415,7 @@ int vmstate_save_state_v(QEMUFile *f, const VMStateDescription *vmsd,
|
||||
}
|
||||
|
||||
if (vmdesc) {
|
||||
json_end_array(vmdesc);
|
||||
json_writer_end_array(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,
|
||||
void *opaque, QJSON *vmdesc)
|
||||
void *opaque, JSONWriter *vmdesc)
|
||||
{
|
||||
const VMStateDescription **sub = vmsd->subsections;
|
||||
bool vmdesc_has_subsections = false;
|
||||
@ -507,11 +509,11 @@ static int vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
|
||||
if (vmdesc) {
|
||||
/* Only create subsection array when we have any */
|
||||
if (!vmdesc_has_subsections) {
|
||||
json_start_array(vmdesc, "subsections");
|
||||
json_writer_start_array(vmdesc, "subsections");
|
||||
vmdesc_has_subsections = true;
|
||||
}
|
||||
|
||||
json_start_object(vmdesc, NULL);
|
||||
json_writer_start_object(vmdesc, NULL);
|
||||
}
|
||||
|
||||
qemu_put_byte(f, QEMU_VM_SUBSECTION);
|
||||
@ -525,14 +527,14 @@ static int vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
|
||||
}
|
||||
|
||||
if (vmdesc) {
|
||||
json_end_object(vmdesc);
|
||||
json_writer_end_object(vmdesc);
|
||||
}
|
||||
}
|
||||
sub++;
|
||||
}
|
||||
|
||||
if (vmdesc_has_subsections) {
|
||||
json_end_array(vmdesc);
|
||||
json_writer_end_array(vmdesc);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -1255,7 +1255,8 @@ void hmp_migrate_set_capability(Monitor *mon, const QDict *qdict)
|
||||
const char *cap = qdict_get_str(qdict, "capability");
|
||||
bool state = qdict_get_bool(qdict, "state");
|
||||
Error *err = NULL;
|
||||
MigrationCapabilityStatusList *caps = g_malloc0(sizeof(*caps));
|
||||
MigrationCapabilityStatusList *caps = NULL;
|
||||
MigrationCapabilityStatus *value;
|
||||
int val;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
caps->value = g_malloc0(sizeof(*caps->value));
|
||||
caps->value->capability = val;
|
||||
caps->value->state = state;
|
||||
caps->next = NULL;
|
||||
value = g_malloc0(sizeof(*value));
|
||||
value->capability = val;
|
||||
value->state = state;
|
||||
QAPI_LIST_PREPEND(caps, value);
|
||||
qmp_migrate_set_capabilities(caps, &err);
|
||||
qapi_free_MigrationCapabilityStatusList(caps);
|
||||
|
||||
end:
|
||||
qapi_free_MigrationCapabilityStatusList(caps);
|
||||
hmp_handle_error(mon, err);
|
||||
}
|
||||
|
||||
|
@ -136,11 +136,7 @@ char *qmp_human_monitor_command(const char *command_line, bool has_cpu_index,
|
||||
handle_hmp_command(&hmp, command_line);
|
||||
|
||||
WITH_QEMU_LOCK_GUARD(&hmp.common.mon_lock) {
|
||||
if (qstring_get_length(hmp.common.outbuf) > 0) {
|
||||
output = g_strdup(qstring_get_str(hmp.common.outbuf));
|
||||
} else {
|
||||
output = g_strdup("");
|
||||
}
|
||||
output = g_strdup(hmp.common.outbuf->str);
|
||||
}
|
||||
|
||||
out:
|
||||
@ -1434,33 +1430,26 @@ FdsetInfoList *qmp_query_fdsets(Error **errp)
|
||||
|
||||
QEMU_LOCK_GUARD(&mon_fdsets_lock);
|
||||
QLIST_FOREACH(mon_fdset, &mon_fdsets, next) {
|
||||
FdsetInfoList *fdset_info = g_malloc0(sizeof(*fdset_info));
|
||||
FdsetFdInfoList *fdsetfd_list = NULL;
|
||||
FdsetInfo *fdset_info = g_malloc0(sizeof(*fdset_info));
|
||||
|
||||
fdset_info->value = g_malloc0(sizeof(*fdset_info->value));
|
||||
fdset_info->value->fdset_id = mon_fdset->id;
|
||||
fdset_info->fdset_id = mon_fdset->id;
|
||||
|
||||
QLIST_FOREACH(mon_fdset_fd, &mon_fdset->fds, next) {
|
||||
FdsetFdInfoList *fdsetfd_info;
|
||||
FdsetFdInfo *fdsetfd_info;
|
||||
|
||||
fdsetfd_info = g_malloc0(sizeof(*fdsetfd_info));
|
||||
fdsetfd_info->value = g_malloc0(sizeof(*fdsetfd_info->value));
|
||||
fdsetfd_info->value->fd = mon_fdset_fd->fd;
|
||||
fdsetfd_info->fd = mon_fdset_fd->fd;
|
||||
if (mon_fdset_fd->opaque) {
|
||||
fdsetfd_info->value->has_opaque = true;
|
||||
fdsetfd_info->value->opaque = g_strdup(mon_fdset_fd->opaque);
|
||||
fdsetfd_info->has_opaque = true;
|
||||
fdsetfd_info->opaque = g_strdup(mon_fdset_fd->opaque);
|
||||
} else {
|
||||
fdsetfd_info->value->has_opaque = false;
|
||||
fdsetfd_info->has_opaque = false;
|
||||
}
|
||||
|
||||
fdsetfd_info->next = fdsetfd_list;
|
||||
fdsetfd_list = fdsetfd_info;
|
||||
QAPI_LIST_PREPEND(fdset_info->fds, fdsetfd_info);
|
||||
}
|
||||
|
||||
fdset_info->value->fds = fdsetfd_list;
|
||||
|
||||
fdset_info->next = fdset_list;
|
||||
fdset_list = fdset_info;
|
||||
QAPI_LIST_PREPEND(fdset_list, fdset_info);
|
||||
}
|
||||
|
||||
return fdset_list;
|
||||
|
@ -105,7 +105,7 @@ struct Monitor {
|
||||
* Members that are protected by the per-monitor lock
|
||||
*/
|
||||
QLIST_HEAD(, mon_fd_t) fds;
|
||||
QString *outbuf;
|
||||
GString *outbuf;
|
||||
guint out_watch;
|
||||
/* Read under either BQL or mon_lock, written with BQL+mon_lock. */
|
||||
int mux_out;
|
||||
|
@ -29,7 +29,6 @@
|
||||
#include "qapi/qapi-emit-events.h"
|
||||
#include "qapi/qapi-visit-control.h"
|
||||
#include "qapi/qmp/qdict.h"
|
||||
#include "qapi/qmp/qstring.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qemu/option.h"
|
||||
#include "sysemu/qtest.h"
|
||||
@ -181,22 +180,19 @@ static void monitor_flush_locked(Monitor *mon)
|
||||
return;
|
||||
}
|
||||
|
||||
buf = qstring_get_str(mon->outbuf);
|
||||
len = qstring_get_length(mon->outbuf);
|
||||
buf = mon->outbuf->str;
|
||||
len = mon->outbuf->len;
|
||||
|
||||
if (len && !mon->mux_out) {
|
||||
rc = qemu_chr_fe_write(&mon->chr, (const uint8_t *) buf, len);
|
||||
if ((rc < 0 && errno != EAGAIN) || (rc == len)) {
|
||||
/* all flushed or error */
|
||||
qobject_unref(mon->outbuf);
|
||||
mon->outbuf = qstring_new();
|
||||
g_string_truncate(mon->outbuf, 0);
|
||||
return;
|
||||
}
|
||||
if (rc > 0) {
|
||||
/* partial write */
|
||||
QString *tmp = qstring_from_str(buf + rc);
|
||||
qobject_unref(mon->outbuf);
|
||||
mon->outbuf = tmp;
|
||||
g_string_erase(mon->outbuf, 0, rc);
|
||||
}
|
||||
if (mon->out_watch == 0) {
|
||||
mon->out_watch =
|
||||
@ -223,9 +219,9 @@ int monitor_puts(Monitor *mon, const char *str)
|
||||
for (i = 0; str[i]; i++) {
|
||||
c = str[i];
|
||||
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') {
|
||||
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);
|
||||
mon->is_qmp = is_qmp;
|
||||
mon->outbuf = qstring_new();
|
||||
mon->outbuf = g_string_new(NULL);
|
||||
mon->skip_flush = skip_flush;
|
||||
mon->use_io_thread = use_io_thread;
|
||||
}
|
||||
@ -616,7 +612,7 @@ void monitor_data_destroy(Monitor *mon)
|
||||
} else {
|
||||
readline_free(container_of(mon, MonitorHMP, common)->rs);
|
||||
}
|
||||
qobject_unref(mon->outbuf);
|
||||
g_string_free(mon->outbuf, true);
|
||||
qemu_mutex_destroy(&mon->mon_lock);
|
||||
}
|
||||
|
||||
|
@ -138,18 +138,18 @@ EventInfoList *qmp_query_events(Error **errp)
|
||||
* QAPIEvent_str() and QAPIEvent_lookup[]. When the command goes,
|
||||
* they should go, too.
|
||||
*/
|
||||
EventInfoList *info, *ev_list = NULL;
|
||||
EventInfoList *ev_list = NULL;
|
||||
QAPIEvent e;
|
||||
|
||||
for (e = 0 ; e < QAPI_EVENT__MAX ; e++) {
|
||||
const char *event_name = QAPIEvent_str(e);
|
||||
EventInfo *info;
|
||||
|
||||
assert(event_name != NULL);
|
||||
info = g_malloc0(sizeof(*info));
|
||||
info->value = g_malloc0(sizeof(*info->value));
|
||||
info->value->name = g_strdup(event_name);
|
||||
info->name = g_strdup(event_name);
|
||||
|
||||
info->next = ev_list;
|
||||
ev_list = info;
|
||||
QAPI_LIST_PREPEND(ev_list, info);
|
||||
}
|
||||
|
||||
return ev_list;
|
||||
|
@ -31,7 +31,6 @@
|
||||
#include "qapi/qmp/qdict.h"
|
||||
#include "qapi/qmp/qjson.h"
|
||||
#include "qapi/qmp/qlist.h"
|
||||
#include "qapi/qmp/qstring.h"
|
||||
#include "trace.h"
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
|
||||
qstring_append_chr(json, '\n');
|
||||
monitor_puts(&mon->common, qstring_get_str(json));
|
||||
g_string_append_c(json, '\n');
|
||||
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;
|
||||
qemu_mutex_unlock(&mon->qmp_queue_lock);
|
||||
if (req_obj->req) {
|
||||
QDict *qdict = qobject_to(QDict, req_obj->req);
|
||||
QObject *id = qdict ? qdict_get(qdict, "id") : NULL;
|
||||
trace_monitor_qmp_cmd_in_band(qobject_get_try_str(id) ?: "");
|
||||
if (trace_event_get_state(TRACE_MONITOR_QMP_CMD_IN_BAND)) {
|
||||
QDict *qdict = qobject_to(QDict, req_obj->req);
|
||||
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);
|
||||
} else {
|
||||
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)
|
||||
{
|
||||
MonitorQMP *mon = opaque;
|
||||
QObject *id = NULL;
|
||||
QDict *qdict;
|
||||
QDict *qdict = qobject_to(QDict, req);
|
||||
QMPRequest *req_obj;
|
||||
|
||||
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)) {
|
||||
QString *req_json = qobject_to_json(req);
|
||||
trace_handle_qmp_command(mon, qstring_get_str(req_json));
|
||||
qobject_unref(req_json);
|
||||
GString *req_json = qobject_to_json(req);
|
||||
trace_handle_qmp_command(mon, req_json->str);
|
||||
g_string_free(req_json, true);
|
||||
}
|
||||
|
||||
if (qdict && qmp_is_oob(qdict)) {
|
||||
/* 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);
|
||||
qobject_unref(req);
|
||||
return;
|
||||
|
@ -258,7 +258,7 @@ static bool print_type_number(Visitor *v, const char *name, double *obj,
|
||||
Error **errp)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
38
qemu-img.c
38
qemu-img.c
@ -33,7 +33,6 @@
|
||||
#include "qapi/qobject-output-visitor.h"
|
||||
#include "qapi/qmp/qjson.h"
|
||||
#include "qapi/qmp/qdict.h"
|
||||
#include "qapi/qmp/qstring.h"
|
||||
#include "qemu/cutils.h"
|
||||
#include "qemu/config-file.h"
|
||||
#include "qemu/option.h"
|
||||
@ -627,18 +626,18 @@ fail:
|
||||
|
||||
static void dump_json_image_check(ImageCheck *check, bool quiet)
|
||||
{
|
||||
QString *str;
|
||||
GString *str;
|
||||
QObject *obj;
|
||||
Visitor *v = qobject_output_visitor_new(&obj);
|
||||
|
||||
visit_type_ImageCheck(v, NULL, &check, &error_abort);
|
||||
visit_complete(v, &obj);
|
||||
str = qobject_to_json_pretty(obj);
|
||||
str = qobject_to_json_pretty(obj, true);
|
||||
assert(str != NULL);
|
||||
qprintf(quiet, "%s\n", qstring_get_str(str));
|
||||
qprintf(quiet, "%s\n", str->str);
|
||||
qobject_unref(obj);
|
||||
visit_free(v);
|
||||
qobject_unref(str);
|
||||
g_string_free(str, true);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
BlockDirtyBitmapMergeSource *merge_src;
|
||||
BlockDirtyBitmapMergeSourceList *list;
|
||||
BlockDirtyBitmapMergeSourceList *list = NULL;
|
||||
|
||||
merge_src = g_new0(BlockDirtyBitmapMergeSource, 1);
|
||||
merge_src->type = QTYPE_QDICT;
|
||||
merge_src->u.external.node = g_strdup(src_node);
|
||||
merge_src->u.external.name = g_strdup(src_name);
|
||||
list = g_new0(BlockDirtyBitmapMergeSourceList, 1);
|
||||
list->value = merge_src;
|
||||
QAPI_LIST_PREPEND(list, merge_src);
|
||||
qmp_block_dirty_bitmap_merge(dst_node, dst_name, list, errp);
|
||||
qapi_free_BlockDirtyBitmapMergeSourceList(list);
|
||||
}
|
||||
@ -2790,34 +2788,34 @@ static void dump_snapshots(BlockDriverState *bs)
|
||||
|
||||
static void dump_json_image_info_list(ImageInfoList *list)
|
||||
{
|
||||
QString *str;
|
||||
GString *str;
|
||||
QObject *obj;
|
||||
Visitor *v = qobject_output_visitor_new(&obj);
|
||||
|
||||
visit_type_ImageInfoList(v, NULL, &list, &error_abort);
|
||||
visit_complete(v, &obj);
|
||||
str = qobject_to_json_pretty(obj);
|
||||
str = qobject_to_json_pretty(obj, true);
|
||||
assert(str != NULL);
|
||||
printf("%s\n", qstring_get_str(str));
|
||||
printf("%s\n", str->str);
|
||||
qobject_unref(obj);
|
||||
visit_free(v);
|
||||
qobject_unref(str);
|
||||
g_string_free(str, true);
|
||||
}
|
||||
|
||||
static void dump_json_image_info(ImageInfo *info)
|
||||
{
|
||||
QString *str;
|
||||
GString *str;
|
||||
QObject *obj;
|
||||
Visitor *v = qobject_output_visitor_new(&obj);
|
||||
|
||||
visit_type_ImageInfo(v, NULL, &info, &error_abort);
|
||||
visit_complete(v, &obj);
|
||||
str = qobject_to_json_pretty(obj);
|
||||
str = qobject_to_json_pretty(obj, true);
|
||||
assert(str != NULL);
|
||||
printf("%s\n", qstring_get_str(str));
|
||||
printf("%s\n", str->str);
|
||||
qobject_unref(obj);
|
||||
visit_free(v);
|
||||
qobject_unref(str);
|
||||
g_string_free(str, true);
|
||||
}
|
||||
|
||||
static void dump_human_image_info_list(ImageInfoList *list)
|
||||
@ -5237,18 +5235,18 @@ out:
|
||||
|
||||
static void dump_json_block_measure_info(BlockMeasureInfo *info)
|
||||
{
|
||||
QString *str;
|
||||
GString *str;
|
||||
QObject *obj;
|
||||
Visitor *v = qobject_output_visitor_new(&obj);
|
||||
|
||||
visit_type_BlockMeasureInfo(v, NULL, &info, &error_abort);
|
||||
visit_complete(v, &obj);
|
||||
str = qobject_to_json_pretty(obj);
|
||||
str = qobject_to_json_pretty(obj, true);
|
||||
assert(str != NULL);
|
||||
printf("%s\n", qstring_get_str(str));
|
||||
printf("%s\n", str->str);
|
||||
qobject_unref(obj);
|
||||
visit_free(v);
|
||||
qobject_unref(str);
|
||||
g_string_free(str, true);
|
||||
}
|
||||
|
||||
static int img_measure(int argc, char **argv)
|
||||
|
@ -293,17 +293,12 @@ qmp_guest_ssh_get_authorized_keys(const char *username, Error **errp)
|
||||
|
||||
ret = g_new0(GuestAuthorizedKeys, 1);
|
||||
for (i = 0; authkeys[i] != NULL; i++) {
|
||||
strList *new;
|
||||
|
||||
g_strstrip(authkeys[i]);
|
||||
if (!authkeys[i][0] || authkeys[i][0] == '#') {
|
||||
continue;
|
||||
}
|
||||
|
||||
new = g_new0(strList, 1);
|
||||
new->value = g_strdup(authkeys[i]);
|
||||
new->next = ret->keys;
|
||||
ret->keys = new;
|
||||
QAPI_LIST_PREPEND(ret->keys, g_strdup(authkeys[i]));
|
||||
}
|
||||
|
||||
return g_steal_pointer(&ret);
|
||||
|
@ -1036,7 +1036,6 @@ static void build_guest_fsinfo_for_real_device(char const *syspath,
|
||||
{
|
||||
GuestDiskAddress *disk;
|
||||
GuestPCIAddress *pciaddr;
|
||||
GuestDiskAddressList *list = NULL;
|
||||
bool has_hwinf;
|
||||
#ifdef CONFIG_LIBUDEV
|
||||
struct udev *udev = NULL;
|
||||
@ -1053,9 +1052,6 @@ static void build_guest_fsinfo_for_real_device(char const *syspath,
|
||||
disk->pci_controller = pciaddr;
|
||||
disk->bus_type = GUEST_DISK_BUS_TYPE_UNKNOWN;
|
||||
|
||||
list = g_new0(GuestDiskAddressList, 1);
|
||||
list->value = disk;
|
||||
|
||||
#ifdef CONFIG_LIBUDEV
|
||||
udev = udev_new();
|
||||
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) {
|
||||
list->next = fs->disk;
|
||||
fs->disk = list;
|
||||
QAPI_LIST_PREPEND(fs->disk, disk);
|
||||
} 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;
|
||||
while ((dep = g_dir_read_name(dp_deps)) != NULL) {
|
||||
g_autofree char *dep_dir = NULL;
|
||||
strList *dep_item = NULL;
|
||||
char *dev_name;
|
||||
|
||||
/* 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);
|
||||
if (dev_name != NULL) {
|
||||
g_debug(" adding dependent device: %s", dev_name);
|
||||
dep_item = g_new0(strList, 1);
|
||||
dep_item->value = dev_name;
|
||||
dep_item->next = disk->dependencies;
|
||||
disk->dependencies = dep_item;
|
||||
QAPI_LIST_PREPEND(disk->dependencies, dev_name);
|
||||
}
|
||||
}
|
||||
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_dev)
|
||||
{
|
||||
GuestDiskInfoList *item, *ret = list;
|
||||
GuestDiskInfoList *ret = list;
|
||||
struct dirent *de_disk;
|
||||
DIR *dp_disk = NULL;
|
||||
size_t len = strlen(disk_name);
|
||||
@ -1352,15 +1343,9 @@ static GuestDiskInfoList *get_disk_partitions(
|
||||
partition->name = dev_name;
|
||||
partition->partition = true;
|
||||
/* Add parent disk as dependent for easier tracking of hierarchy */
|
||||
partition->dependencies = g_new0(strList, 1);
|
||||
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(partition->dependencies, g_strdup(disk_dev));
|
||||
|
||||
QAPI_LIST_PREPEND(ret, partition);
|
||||
}
|
||||
closedir(dp_disk);
|
||||
|
||||
@ -1369,7 +1354,7 @@ static GuestDiskInfoList *get_disk_partitions(
|
||||
|
||||
GuestDiskInfoList *qmp_guest_get_disks(Error **errp)
|
||||
{
|
||||
GuestDiskInfoList *item, *ret = NULL;
|
||||
GuestDiskInfoList *ret = NULL;
|
||||
GuestDiskInfo *disk;
|
||||
DIR *dp = NULL;
|
||||
struct dirent *de = NULL;
|
||||
@ -1415,10 +1400,7 @@ GuestDiskInfoList *qmp_guest_get_disks(Error **errp)
|
||||
disk->partition = false;
|
||||
disk->alias = get_alias_for_syspath(disk_dir);
|
||||
disk->has_alias = (disk->alias != NULL);
|
||||
item = g_new0(GuestDiskInfoList, 1);
|
||||
item->value = disk;
|
||||
item->next = ret;
|
||||
ret = item;
|
||||
QAPI_LIST_PREPEND(ret, disk);
|
||||
|
||||
/* Get address for non-virtual devices */
|
||||
bool is_virtual = is_disk_virtual(disk_dir, &local_err);
|
||||
@ -1495,7 +1477,7 @@ GuestFilesystemInfoList *qmp_guest_get_fsinfo(Error **errp)
|
||||
{
|
||||
FsMountList mounts;
|
||||
struct FsMount *mount;
|
||||
GuestFilesystemInfoList *new, *ret = NULL;
|
||||
GuestFilesystemInfoList *ret = NULL;
|
||||
Error *local_err = NULL;
|
||||
|
||||
QTAILQ_INIT(&mounts);
|
||||
@ -1508,10 +1490,7 @@ GuestFilesystemInfoList *qmp_guest_get_fsinfo(Error **errp)
|
||||
QTAILQ_FOREACH(mount, &mounts, next) {
|
||||
g_debug("Building guest fsinfo for '%s'", mount->dirname);
|
||||
|
||||
new = g_malloc0(sizeof(*ret));
|
||||
new->value = build_guest_fsinfo(mount, &local_err);
|
||||
new->next = ret;
|
||||
ret = new;
|
||||
QAPI_LIST_PREPEND(ret, build_guest_fsinfo(mount, &local_err));
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
qapi_free_GuestFilesystemInfoList(ret);
|
||||
@ -1777,7 +1756,6 @@ GuestFilesystemTrimResponse *
|
||||
qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **errp)
|
||||
{
|
||||
GuestFilesystemTrimResponse *response;
|
||||
GuestFilesystemTrimResultList *list;
|
||||
GuestFilesystemTrimResult *result;
|
||||
int ret = 0;
|
||||
FsMountList mounts;
|
||||
@ -1801,10 +1779,7 @@ qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **errp)
|
||||
result = g_malloc0(sizeof(*result));
|
||||
result->path = g_strdup(mount->dirname);
|
||||
|
||||
list = g_malloc0(sizeof(*list));
|
||||
list->value = result;
|
||||
list->next = response->paths;
|
||||
response->paths = list;
|
||||
QAPI_LIST_PREPEND(response->paths, result);
|
||||
|
||||
fd = qemu_open_old(mount->dirname, O_RDONLY);
|
||||
if (fd == -1) {
|
||||
|
@ -874,7 +874,7 @@ err_close:
|
||||
static GuestDiskAddressList *build_guest_disk_info(char *guid, Error **errp)
|
||||
{
|
||||
Error *local_err = NULL;
|
||||
GuestDiskAddressList *list = NULL, *cur_item = NULL;
|
||||
GuestDiskAddressList *list = NULL;
|
||||
GuestDiskAddress *disk = NULL;
|
||||
int i;
|
||||
HANDLE vol_h;
|
||||
@ -926,10 +926,8 @@ static GuestDiskAddressList *build_guest_disk_info(char *guid, Error **errp)
|
||||
error_free(local_err);
|
||||
goto out;
|
||||
}
|
||||
list = g_malloc0(sizeof(*list));
|
||||
list->value = disk;
|
||||
QAPI_LIST_PREPEND(list, disk);
|
||||
disk = NULL;
|
||||
list->next = NULL;
|
||||
goto out;
|
||||
} else {
|
||||
error_setg_win32(errp, GetLastError(),
|
||||
@ -960,11 +958,8 @@ static GuestDiskAddressList *build_guest_disk_info(char *guid, Error **errp)
|
||||
error_propagate(errp, local_err);
|
||||
goto out;
|
||||
}
|
||||
cur_item = g_malloc0(sizeof(*list));
|
||||
cur_item->value = disk;
|
||||
QAPI_LIST_PREPEND(list, disk);
|
||||
disk = NULL;
|
||||
cur_item->next = list;
|
||||
list = cur_item;
|
||||
}
|
||||
|
||||
|
||||
@ -982,7 +977,7 @@ out:
|
||||
GuestDiskInfoList *qmp_guest_get_disks(Error **errp)
|
||||
{
|
||||
ERRP_GUARD();
|
||||
GuestDiskInfoList *new = NULL, *ret = NULL;
|
||||
GuestDiskInfoList *ret = NULL;
|
||||
HDEVINFO dev_info;
|
||||
SP_DEVICE_INTERFACE_DATA dev_iface_data;
|
||||
int i;
|
||||
@ -1064,10 +1059,7 @@ GuestDiskInfoList *qmp_guest_get_disks(Error **errp)
|
||||
disk->has_address = true;
|
||||
}
|
||||
|
||||
new = g_malloc0(sizeof(GuestDiskInfoList));
|
||||
new->value = disk;
|
||||
new->next = ret;
|
||||
ret = new;
|
||||
QAPI_LIST_PREPEND(ret, disk);
|
||||
}
|
||||
|
||||
SetupDiDestroyDeviceInfoList(dev_info);
|
||||
@ -1165,7 +1157,7 @@ free:
|
||||
GuestFilesystemInfoList *qmp_guest_get_fsinfo(Error **errp)
|
||||
{
|
||||
HANDLE vol_h;
|
||||
GuestFilesystemInfoList *new, *ret = NULL;
|
||||
GuestFilesystemInfoList *ret = NULL;
|
||||
char guid[256];
|
||||
|
||||
vol_h = FindFirstVolume(guid, sizeof(guid));
|
||||
@ -1183,10 +1175,7 @@ GuestFilesystemInfoList *qmp_guest_get_fsinfo(Error **errp)
|
||||
error_free(local_err);
|
||||
continue;
|
||||
}
|
||||
new = g_malloc(sizeof(*ret));
|
||||
new->value = info;
|
||||
new->next = ret;
|
||||
ret = new;
|
||||
QAPI_LIST_PREPEND(ret, info);
|
||||
} while (FindNextVolume(vol_h, guid, sizeof(guid)));
|
||||
|
||||
if (GetLastError() != ERROR_NO_MORE_FILES) {
|
||||
@ -1330,7 +1319,6 @@ qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **errp)
|
||||
|
||||
do {
|
||||
GuestFilesystemTrimResult *res;
|
||||
GuestFilesystemTrimResultList *list;
|
||||
PWCHAR uc_path;
|
||||
DWORD char_count = 0;
|
||||
char *path, *out;
|
||||
@ -1369,11 +1357,7 @@ qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **errp)
|
||||
|
||||
res->path = path;
|
||||
|
||||
list = g_new0(GuestFilesystemTrimResultList, 1);
|
||||
list->value = res;
|
||||
list->next = resp->paths;
|
||||
|
||||
resp->paths = list;
|
||||
QAPI_LIST_PREPEND(resp->paths, res);
|
||||
|
||||
memset(argv, 0, sizeof(argv));
|
||||
argv[0] = (gchar *)"defrag.exe";
|
||||
|
@ -66,17 +66,13 @@ static void qmp_command_info(const QmpCommand *cmd, void *opaque)
|
||||
{
|
||||
GuestAgentInfo *info = opaque;
|
||||
GuestAgentCommandInfo *cmd_info;
|
||||
GuestAgentCommandInfoList *cmd_info_list;
|
||||
|
||||
cmd_info = g_new0(GuestAgentCommandInfo, 1);
|
||||
cmd_info->name = g_strdup(qmp_command_name(cmd));
|
||||
cmd_info->enabled = qmp_command_is_enabled(cmd);
|
||||
cmd_info->success_response = qmp_has_success_response(cmd);
|
||||
|
||||
cmd_info_list = g_new0(GuestAgentCommandInfoList, 1);
|
||||
cmd_info_list->value = cmd_info;
|
||||
cmd_info_list->next = info->supported_commands;
|
||||
info->supported_commands = cmd_info_list;
|
||||
QAPI_LIST_PREPEND(info->supported_commands, cmd_info);
|
||||
}
|
||||
|
||||
struct GuestAgentInfo *qmp_guest_info(Error **errp)
|
||||
|
22
qga/main.c
22
qga/main.c
@ -22,7 +22,6 @@
|
||||
#include "qapi/qmp/json-parser.h"
|
||||
#include "qapi/qmp/qdict.h"
|
||||
#include "qapi/qmp/qjson.h"
|
||||
#include "qapi/qmp/qstring.h"
|
||||
#include "guest-agent-core.h"
|
||||
#include "qga-qapi-init-commands.h"
|
||||
#include "qapi/qmp/qerror.h"
|
||||
@ -528,8 +527,7 @@ fail:
|
||||
|
||||
static int send_response(GAState *s, const QDict *rsp)
|
||||
{
|
||||
const char *buf;
|
||||
QString *payload_qstr, *response_qstr;
|
||||
GString *response;
|
||||
GIOStatus status;
|
||||
|
||||
g_assert(s->channel);
|
||||
@ -538,25 +536,19 @@ static int send_response(GAState *s, const QDict *rsp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
payload_qstr = qobject_to_json(QOBJECT(rsp));
|
||||
if (!payload_qstr) {
|
||||
response = qobject_to_json(QOBJECT(rsp));
|
||||
if (!response) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (s->delimit_response) {
|
||||
s->delimit_response = false;
|
||||
response_qstr = qstring_new();
|
||||
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;
|
||||
g_string_prepend_c(response, QGA_SENTINEL_BYTE);
|
||||
}
|
||||
|
||||
qstring_append_chr(response_qstr, '\n');
|
||||
buf = qstring_get_str(response_qstr);
|
||||
status = ga_channel_write_all(s->channel, buf, strlen(buf));
|
||||
qobject_unref(response_qstr);
|
||||
g_string_append_c(response, '\n');
|
||||
status = ga_channel_write_all(s->channel, response->str, response->len);
|
||||
g_string_free(response, true);
|
||||
if (status != G_IO_STATUS_NORMAL) {
|
||||
return -EIO;
|
||||
}
|
||||
|
@ -130,7 +130,7 @@ static int cvt4hex(const char *s)
|
||||
static QString *parse_string(JSONParserContext *ctxt, JSONToken *token)
|
||||
{
|
||||
const char *ptr = token->str;
|
||||
QString *str;
|
||||
GString *str;
|
||||
char quote;
|
||||
const char *beg;
|
||||
int cp, trailing;
|
||||
@ -140,7 +140,7 @@ static QString *parse_string(JSONParserContext *ctxt, JSONToken *token)
|
||||
|
||||
assert(*ptr == '"' || *ptr == '\'');
|
||||
quote = *ptr++;
|
||||
str = qstring_new();
|
||||
str = g_string_new(NULL);
|
||||
|
||||
while (*ptr != quote) {
|
||||
assert(*ptr);
|
||||
@ -149,31 +149,31 @@ static QString *parse_string(JSONParserContext *ctxt, JSONToken *token)
|
||||
beg = ptr++;
|
||||
switch (*ptr++) {
|
||||
case '"':
|
||||
qstring_append_chr(str, '"');
|
||||
g_string_append_c(str, '"');
|
||||
break;
|
||||
case '\'':
|
||||
qstring_append_chr(str, '\'');
|
||||
g_string_append_c(str, '\'');
|
||||
break;
|
||||
case '\\':
|
||||
qstring_append_chr(str, '\\');
|
||||
g_string_append_c(str, '\\');
|
||||
break;
|
||||
case '/':
|
||||
qstring_append_chr(str, '/');
|
||||
g_string_append_c(str, '/');
|
||||
break;
|
||||
case 'b':
|
||||
qstring_append_chr(str, '\b');
|
||||
g_string_append_c(str, '\b');
|
||||
break;
|
||||
case 'f':
|
||||
qstring_append_chr(str, '\f');
|
||||
g_string_append_c(str, '\f');
|
||||
break;
|
||||
case 'n':
|
||||
qstring_append_chr(str, '\n');
|
||||
g_string_append_c(str, '\n');
|
||||
break;
|
||||
case 'r':
|
||||
qstring_append_chr(str, '\r');
|
||||
g_string_append_c(str, '\r');
|
||||
break;
|
||||
case 't':
|
||||
qstring_append_chr(str, '\t');
|
||||
g_string_append_c(str, '\t');
|
||||
break;
|
||||
case 'u':
|
||||
cp = cvt4hex(ptr);
|
||||
@ -200,7 +200,7 @@ static QString *parse_string(JSONParserContext *ctxt, JSONToken *token)
|
||||
(int)(ptr - beg), beg);
|
||||
goto out;
|
||||
}
|
||||
qstring_append(str, utf8_buf);
|
||||
g_string_append(str, utf8_buf);
|
||||
break;
|
||||
default:
|
||||
parse_error(ctxt, token, "invalid escape sequence in string");
|
||||
@ -225,14 +225,14 @@ static QString *parse_string(JSONParserContext *ctxt, JSONToken *token)
|
||||
ptr = end;
|
||||
len = mod_utf8_encode(utf8_buf, sizeof(utf8_buf), cp);
|
||||
assert(len >= 0);
|
||||
qstring_append(str, utf8_buf);
|
||||
g_string_append(str, utf8_buf);
|
||||
}
|
||||
}
|
||||
|
||||
return str;
|
||||
return qstring_from_gstring(str);
|
||||
|
||||
out:
|
||||
qobject_unref(str);
|
||||
g_string_free(str, true);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
247
qobject/json-writer.c
Normal file
247
qobject/json-writer.c
Normal 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);
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
util_ss.add(files('qnull.c', 'qnum.c', 'qstring.c', 'qdict.c', 'qlist.c', 'qbool.c',
|
||||
'qlit.c', 'qjson.c', 'qobject.c', 'json-lexer.c', 'json-streamer.c', 'json-parser.c',
|
||||
util_ss.add(files('qnull.c', 'qnum.c', 'qstring.c', 'qdict.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'))
|
||||
|
@ -13,6 +13,7 @@
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/qmp/qbool.h"
|
||||
#include "qobject-internal.h"
|
||||
|
||||
/**
|
||||
* qbool_from_bool(): Create a new QBool from a bool
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "qapi/qmp/qbool.h"
|
||||
#include "qapi/qmp/qnull.h"
|
||||
#include "qapi/qmp/qstring.h"
|
||||
#include "qobject-internal.h"
|
||||
|
||||
/**
|
||||
* qdict_new(): Create a new QDict
|
||||
|
144
qobject/qjson.c
144
qobject/qjson.c
@ -14,13 +14,13 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/qmp/json-parser.h"
|
||||
#include "qapi/qmp/json-writer.h"
|
||||
#include "qapi/qmp/qjson.h"
|
||||
#include "qapi/qmp/qbool.h"
|
||||
#include "qapi/qmp/qdict.h"
|
||||
#include "qapi/qmp/qlist.h"
|
||||
#include "qapi/qmp/qnum.h"
|
||||
#include "qapi/qmp/qstring.h"
|
||||
#include "qemu/unicode.h"
|
||||
|
||||
typedef struct JSONParsingState
|
||||
{
|
||||
@ -149,144 +149,69 @@ QDict *qdict_from_jsonf_nofail(const char *string, ...)
|
||||
return qdict;
|
||||
}
|
||||
|
||||
static void to_json(const QObject *obj, QString *str, int pretty, int indent);
|
||||
|
||||
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)
|
||||
static void to_json(JSONWriter *writer, const char *name,
|
||||
const QObject *obj)
|
||||
{
|
||||
switch (qobject_type(obj)) {
|
||||
case QTYPE_QNULL:
|
||||
qstring_append(str, "null");
|
||||
json_writer_null(writer, name);
|
||||
break;
|
||||
case QTYPE_QNUM: {
|
||||
QNum *val = qobject_to(QNum, obj);
|
||||
char *buffer = qnum_to_string(val);
|
||||
qstring_append(str, buffer);
|
||||
g_free(buffer);
|
||||
|
||||
switch (val->kind) {
|
||||
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;
|
||||
}
|
||||
case QTYPE_QSTRING: {
|
||||
QString *val = qobject_to(QString, obj);
|
||||
const char *ptr;
|
||||
int cp;
|
||||
char buf[16];
|
||||
char *end;
|
||||
|
||||
ptr = 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, "\"");
|
||||
json_writer_str(writer, name, qstring_get_str(val));
|
||||
break;
|
||||
}
|
||||
case QTYPE_QDICT: {
|
||||
QDict *val = qobject_to(QDict, obj);
|
||||
const char *comma = pretty ? "," : ", ";
|
||||
const char *sep = "";
|
||||
const QDictEntry *entry;
|
||||
QString *qkey;
|
||||
|
||||
qstring_append(str, "{");
|
||||
json_writer_start_object(writer, name);
|
||||
|
||||
for (entry = qdict_first(val);
|
||||
entry;
|
||||
entry = qdict_next(val, entry)) {
|
||||
qstring_append(str, sep);
|
||||
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;
|
||||
to_json(writer, qdict_entry_key(entry), qdict_entry_value(entry));
|
||||
}
|
||||
|
||||
json_pretty_newline(str, pretty, indent);
|
||||
qstring_append(str, "}");
|
||||
json_writer_end_object(writer);
|
||||
break;
|
||||
}
|
||||
case QTYPE_QLIST: {
|
||||
QList *val = qobject_to(QList, obj);
|
||||
const char *comma = pretty ? "," : ", ";
|
||||
const char *sep = "";
|
||||
QListEntry *entry;
|
||||
|
||||
qstring_append(str, "[");
|
||||
json_writer_start_array(writer, name);
|
||||
|
||||
QLIST_FOREACH_ENTRY(val, entry) {
|
||||
qstring_append(str, sep);
|
||||
json_pretty_newline(str, pretty, indent + 1);
|
||||
to_json(qlist_entry_obj(entry), str, pretty, indent + 1);
|
||||
sep = comma;
|
||||
to_json(writer, NULL, qlist_entry_obj(entry));
|
||||
}
|
||||
|
||||
json_pretty_newline(str, pretty, indent);
|
||||
qstring_append(str, "]");
|
||||
json_writer_end_array(writer);
|
||||
break;
|
||||
}
|
||||
case QTYPE_QBOOL: {
|
||||
QBool *val = qobject_to(QBool, obj);
|
||||
|
||||
if (qbool_get_bool(val)) {
|
||||
qstring_append(str, "true");
|
||||
} else {
|
||||
qstring_append(str, "false");
|
||||
}
|
||||
json_writer_bool(writer, name, qbool_get_bool(val));
|
||||
break;
|
||||
}
|
||||
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);
|
||||
|
||||
return str;
|
||||
to_json(writer, NULL, obj);
|
||||
return json_writer_get_and_free(writer);
|
||||
}
|
||||
|
||||
QString *qobject_to_json_pretty(const QObject *obj)
|
||||
GString *qobject_to_json(const QObject *obj)
|
||||
{
|
||||
QString *str = qstring_new();
|
||||
|
||||
to_json(obj, str, 1, 0);
|
||||
|
||||
return str;
|
||||
return qobject_to_json_pretty(obj, false);
|
||||
}
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "qapi/qmp/qnum.h"
|
||||
#include "qapi/qmp/qstring.h"
|
||||
#include "qemu/queue.h"
|
||||
#include "qobject-internal.h"
|
||||
|
||||
/**
|
||||
* qlist_new(): Create a new QList
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/qmp/qnull.h"
|
||||
#include "qobject-internal.h"
|
||||
|
||||
QNull qnull_ = {
|
||||
.base = {
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/qmp/qnum.h"
|
||||
#include "qobject-internal.h"
|
||||
|
||||
/**
|
||||
* 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 *buffer;
|
||||
int len;
|
||||
|
||||
switch (qn->kind) {
|
||||
case QNUM_I64:
|
||||
return g_strdup_printf("%" PRId64, qn->u.i64);
|
||||
case QNUM_U64:
|
||||
return g_strdup_printf("%" PRIu64, qn->u.u64);
|
||||
case QNUM_DOUBLE:
|
||||
/* FIXME: snprintf() 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. */
|
||||
/* 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;
|
||||
/* 17 digits suffice for IEEE double */
|
||||
return g_strdup_printf("%.17g", qn->u.dbl);
|
||||
}
|
||||
|
||||
assert(0);
|
||||
|
39
qobject/qobject-internal.h
Normal file
39
qobject/qobject-internal.h
Normal 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
|
@ -14,6 +14,7 @@
|
||||
#include "qapi/qmp/qdict.h"
|
||||
#include "qapi/qmp/qlist.h"
|
||||
#include "qapi/qmp/qstring.h"
|
||||
#include "qobject-internal.h"
|
||||
|
||||
QEMU_BUILD_BUG_MSG(
|
||||
offsetof(QNull, base) != 0 ||
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/qmp/qstring.h"
|
||||
#include "qobject-internal.h"
|
||||
|
||||
/**
|
||||
* qstring_new(): Create a new empty QString
|
||||
@ -23,14 +24,6 @@ QString *qstring_new(void)
|
||||
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
|
||||
*
|
||||
@ -41,18 +34,9 @@ QString *qstring_from_substr(const char *str, size_t start, size_t end)
|
||||
QString *qstring;
|
||||
|
||||
assert(start <= end);
|
||||
|
||||
qstring = g_malloc(sizeof(*qstring));
|
||||
qobject_init(QOBJECT(qstring), QTYPE_QSTRING);
|
||||
|
||||
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;
|
||||
|
||||
qstring->string = g_strndup(str + start, end - start);
|
||||
return qstring;
|
||||
}
|
||||
|
||||
@ -66,48 +50,23 @@ QString *qstring_from_str(const char *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->string[qstring->length++] = c;
|
||||
qstring->string[qstring->length] = 0;
|
||||
QString *qstring;
|
||||
|
||||
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
|
||||
*
|
||||
@ -119,27 +78,6 @@ const char *qstring_get_str(const QString *qstring)
|
||||
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
|
||||
*/
|
||||
@ -149,33 +87,16 @@ bool qstring_is_equal(const QObject *x, const QObject *y)
|
||||
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
|
||||
* object
|
||||
*/
|
||||
void qstring_destroy_obj(QObject *obj)
|
||||
{
|
||||
QString *qs;
|
||||
|
||||
assert(obj != NULL);
|
||||
qstring_free(qobject_to(QString, obj), FALSE);
|
||||
qs = qobject_to(QString, obj);
|
||||
g_free((char *)qs->string);
|
||||
g_free(qs);
|
||||
}
|
||||
|
@ -1415,15 +1415,18 @@ char *object_property_get_str(Object *obj, const char *name,
|
||||
Error **errp)
|
||||
{
|
||||
QObject *ret = object_property_get_qobject(obj, name, errp);
|
||||
QString *qstring;
|
||||
char *retval;
|
||||
|
||||
if (!ret) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
retval = g_strdup(qobject_get_try_str(ret));
|
||||
if (!retval) {
|
||||
qstring = qobject_to(QString, ret);
|
||||
if (!qstring) {
|
||||
error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, "string");
|
||||
retval = NULL;
|
||||
} else {
|
||||
retval = g_strdup(qstring_get_str(qstring));
|
||||
}
|
||||
|
||||
qobject_unref(ret);
|
||||
|
@ -5,7 +5,6 @@
|
||||
#include "qapi/qmp/qdict.h"
|
||||
#include "qapi/qmp/qerror.h"
|
||||
#include "qapi/qmp/qjson.h"
|
||||
#include "qapi/qmp/qstring.h"
|
||||
#include "qapi/qobject-input-visitor.h"
|
||||
#include "qom/object_interfaces.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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,6 @@
|
||||
#include "qapi/qapi-commands-qom.h"
|
||||
#include "qapi/qmp/qdict.h"
|
||||
#include "qapi/qmp/qjson.h"
|
||||
#include "qapi/qmp/qstring.h"
|
||||
#include "qom/object.h"
|
||||
|
||||
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);
|
||||
|
||||
if (err == NULL) {
|
||||
QString *str = qobject_to_json_pretty(obj);
|
||||
monitor_printf(mon, "%s\n", qstring_get_str(str));
|
||||
qobject_unref(str);
|
||||
GString *str = qobject_to_json_pretty(obj, true);
|
||||
monitor_printf(mon, "%s\n", str->str);
|
||||
g_string_free(str, true);
|
||||
}
|
||||
|
||||
qobject_unref(obj);
|
||||
|
@ -46,14 +46,12 @@ ObjectPropertyInfoList *qmp_qom_list(const char *path, Error **errp)
|
||||
|
||||
object_property_iter_init(&iter, obj);
|
||||
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));
|
||||
entry->next = props;
|
||||
props = entry;
|
||||
QAPI_LIST_PREPEND(props, value);
|
||||
|
||||
entry->value->name = g_strdup(prop->name);
|
||||
entry->value->type = g_strdup(prop->type);
|
||||
value->name = g_strdup(prop->name);
|
||||
value->type = g_strdup(prop->type);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
ObjectTypeInfoList *e, **pret = data;
|
||||
ObjectTypeInfoList **pret = data;
|
||||
ObjectTypeInfo *info;
|
||||
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));
|
||||
}
|
||||
|
||||
e = g_malloc0(sizeof(*e));
|
||||
e->value = info;
|
||||
e->next = *pret;
|
||||
*pret = e;
|
||||
QAPI_LIST_PREPEND(*pret, info);
|
||||
}
|
||||
|
||||
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);
|
||||
while ((prop = object_property_iter_next(&iter))) {
|
||||
ObjectPropertyInfo *info;
|
||||
ObjectPropertyInfoList *entry;
|
||||
|
||||
/* Skip Object and DeviceState properties */
|
||||
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->has_default_value = !!info->default_value;
|
||||
|
||||
entry = g_malloc0(sizeof(*entry));
|
||||
entry->value = info;
|
||||
entry->next = prop_list;
|
||||
prop_list = entry;
|
||||
QAPI_LIST_PREPEND(prop_list, info);
|
||||
}
|
||||
|
||||
object_unref(obj);
|
||||
@ -217,7 +208,6 @@ ObjectPropertyInfoList *qmp_qom_list_properties(const char *typename,
|
||||
}
|
||||
while ((prop = object_property_iter_next(&iter))) {
|
||||
ObjectPropertyInfo *info;
|
||||
ObjectPropertyInfoList *entry;
|
||||
|
||||
info = g_malloc0(sizeof(*info));
|
||||
info->name = g_strdup(prop->name);
|
||||
@ -225,10 +215,7 @@ ObjectPropertyInfoList *qmp_qom_list_properties(const char *typename,
|
||||
info->has_description = !!prop->description;
|
||||
info->description = g_strdup(prop->description);
|
||||
|
||||
entry = g_malloc0(sizeof(*entry));
|
||||
entry->value = info;
|
||||
entry->next = prop_list;
|
||||
prop_list = entry;
|
||||
QAPI_LIST_PREPEND(prop_list, info);
|
||||
}
|
||||
|
||||
object_unref(obj);
|
||||
|
@ -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,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, JSONWriter *vmdesc)
|
||||
{
|
||||
CPUAlphaState *env = opaque;
|
||||
qemu_put_be64(f, cpu_alpha_load_fpcr(env));
|
||||
|
@ -8283,7 +8283,6 @@ static void arm_cpu_add_definition(gpointer data, gpointer user_data)
|
||||
{
|
||||
ObjectClass *oc = data;
|
||||
CpuDefinitionInfoList **cpu_list = user_data;
|
||||
CpuDefinitionInfoList *entry;
|
||||
CpuDefinitionInfo *info;
|
||||
const char *typename;
|
||||
|
||||
@ -8293,10 +8292,7 @@ static void arm_cpu_add_definition(gpointer data, gpointer user_data)
|
||||
strlen(typename) - strlen("-" TYPE_ARM_CPU));
|
||||
info->q_typename = g_strdup(typename);
|
||||
|
||||
entry = g_malloc0(sizeof(*entry));
|
||||
entry->value = info;
|
||||
entry->next = *cpu_list;
|
||||
*cpu_list = entry;
|
||||
QAPI_LIST_PREPEND(*cpu_list, info);
|
||||
}
|
||||
|
||||
CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
|
||||
|
@ -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,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, JSONWriter *vmdesc)
|
||||
{
|
||||
ARMCPU *cpu = opaque;
|
||||
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,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, JSONWriter *vmdesc)
|
||||
{
|
||||
ARMCPU *cpu = opaque;
|
||||
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,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, JSONWriter *vmdesc)
|
||||
{
|
||||
ARMCPU *cpu = opaque;
|
||||
|
||||
|
@ -42,15 +42,6 @@ static GICCapability *gic_cap_new(int version)
|
||||
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)
|
||||
{
|
||||
#ifdef CONFIG_KVM
|
||||
@ -84,8 +75,8 @@ GICCapabilityList *qmp_query_gic_capabilities(Error **errp)
|
||||
|
||||
gic_cap_kvm_probe(v2, v3);
|
||||
|
||||
head = gic_cap_list_add(head, v2);
|
||||
head = gic_cap_list_add(head, v3);
|
||||
QAPI_LIST_PREPEND(head, v2);
|
||||
QAPI_LIST_PREPEND(head, v3);
|
||||
|
||||
return head;
|
||||
}
|
||||
|
@ -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,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, JSONWriter *vmdesc)
|
||||
{
|
||||
CPUAVRState *env = opaque;
|
||||
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,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, JSONWriter *vmdesc)
|
||||
{
|
||||
uint32_t *ramp = opaque;
|
||||
uint8_t temp = *ramp >> 16;
|
||||
|
@ -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,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, JSONWriter *vmdesc)
|
||||
{
|
||||
CPUHPPAState *env = opaque;
|
||||
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,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, JSONWriter *vmdesc)
|
||||
{
|
||||
hppa_tlb_entry *ent = opaque;
|
||||
uint32_t val = 0;
|
||||
|
@ -5014,7 +5014,6 @@ static void x86_cpu_definition_entry(gpointer data, gpointer user_data)
|
||||
ObjectClass *oc = data;
|
||||
X86CPUClass *cc = X86_CPU_CLASS(oc);
|
||||
CpuDefinitionInfoList **cpu_list = user_data;
|
||||
CpuDefinitionInfoList *entry;
|
||||
CpuDefinitionInfo *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;
|
||||
}
|
||||
|
||||
entry = g_malloc0(sizeof(*entry));
|
||||
entry->value = info;
|
||||
entry->next = *cpu_list;
|
||||
*cpu_list = entry;
|
||||
QAPI_LIST_PREPEND(*cpu_list, info);
|
||||
}
|
||||
|
||||
CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
|
||||
|
@ -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,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, JSONWriter *vmdesc)
|
||||
{
|
||||
CPUMBState *env = container_of(opaque, CPUMBState, msr);
|
||||
|
||||
|
@ -543,7 +543,6 @@ static void mips_cpu_add_definition(gpointer data, gpointer user_data)
|
||||
{
|
||||
ObjectClass *oc = data;
|
||||
CpuDefinitionInfoList **cpu_list = user_data;
|
||||
CpuDefinitionInfoList *entry;
|
||||
CpuDefinitionInfo *info;
|
||||
const char *typename;
|
||||
|
||||
@ -553,10 +552,7 @@ static void mips_cpu_add_definition(gpointer data, gpointer user_data)
|
||||
strlen(typename) - strlen("-" TYPE_MIPS_CPU));
|
||||
info->q_typename = g_strdup(typename);
|
||||
|
||||
entry = g_malloc0(sizeof(*entry));
|
||||
entry->value = info;
|
||||
entry->next = *cpu_list;
|
||||
*cpu_list = entry;
|
||||
QAPI_LIST_PREPEND(*cpu_list, info);
|
||||
}
|
||||
|
||||
CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
|
||||
|
@ -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,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, JSONWriter *vmdesc)
|
||||
{
|
||||
int i;
|
||||
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,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, JSONWriter *vmdesc)
|
||||
{
|
||||
r4k_tlb_t *v = pv;
|
||||
|
||||
|
@ -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,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, JSONWriter *vmdesc)
|
||||
{
|
||||
CPUOpenRISCState *env = opaque;
|
||||
qemu_put_be32(f, cpu_get_sr(env));
|
||||
|
@ -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,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, JSONWriter *vmdesc)
|
||||
{
|
||||
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,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, JSONWriter *vmdesc)
|
||||
{
|
||||
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,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, JSONWriter *vmdesc)
|
||||
{
|
||||
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,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, JSONWriter *vmdesc)
|
||||
{
|
||||
PowerPCCPU *cpu = opaque;
|
||||
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,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, JSONWriter *vmdesc)
|
||||
{
|
||||
ppc_slb_t *v = pv;
|
||||
|
||||
|
@ -10566,7 +10566,6 @@ static void ppc_cpu_defs_entry(gpointer data, gpointer user_data)
|
||||
ObjectClass *oc = data;
|
||||
CpuDefinitionInfoList **first = user_data;
|
||||
const char *typename;
|
||||
CpuDefinitionInfoList *entry;
|
||||
CpuDefinitionInfo *info;
|
||||
|
||||
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,
|
||||
strlen(typename) - strlen(POWERPC_CPU_TYPE_SUFFIX));
|
||||
|
||||
entry = g_malloc0(sizeof(*entry));
|
||||
entry->value = info;
|
||||
entry->next = *first;
|
||||
*first = entry;
|
||||
QAPI_LIST_PREPEND(*first, info);
|
||||
}
|
||||
|
||||
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++) {
|
||||
PowerPCCPUAlias *alias = &ppc_cpu_aliases[i];
|
||||
ObjectClass *oc;
|
||||
CpuDefinitionInfoList *entry;
|
||||
CpuDefinitionInfo *info;
|
||||
|
||||
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->q_typename = g_strdup(object_class_get_name(oc));
|
||||
|
||||
entry = g_malloc0(sizeof(*entry));
|
||||
entry->value = info;
|
||||
entry->next = cpu_list;
|
||||
cpu_list = entry;
|
||||
QAPI_LIST_PREPEND(cpu_list, info);
|
||||
}
|
||||
|
||||
return cpu_list;
|
||||
|
@ -427,7 +427,6 @@ static void create_cpu_model_list(ObjectClass *klass, void *opaque)
|
||||
{
|
||||
struct CpuDefinitionInfoListData *cpu_list_data = opaque;
|
||||
CpuDefinitionInfoList **cpu_list = &cpu_list_data->list;
|
||||
CpuDefinitionInfoList *entry;
|
||||
CpuDefinitionInfo *info;
|
||||
char *name = g_strdup(object_class_get_name(klass));
|
||||
S390CPUClass *scc = S390_CPU_CLASS(klass);
|
||||
@ -454,10 +453,7 @@ static void create_cpu_model_list(ObjectClass *klass, void *opaque)
|
||||
object_unref(obj);
|
||||
}
|
||||
|
||||
entry = g_new0(CpuDefinitionInfoList, 1);
|
||||
entry->value = info;
|
||||
entry->next = *cpu_list;
|
||||
*cpu_list = entry;
|
||||
QAPI_LIST_PREPEND(*cpu_list, info);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
strList **last = (strList **) opaque;
|
||||
strList *entry;
|
||||
|
||||
entry = g_new0(strList, 1);
|
||||
entry->value = g_strdup(name);
|
||||
entry->next = *last;
|
||||
*last = entry;
|
||||
QAPI_LIST_PREPEND(*last, g_strdup(name));
|
||||
}
|
||||
|
||||
CpuModelCompareInfo *qmp_query_cpu_model_comparison(CpuModelInfo *infoa,
|
||||
|
@ -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,
|
||||
const VMStateField *field, QJSON *vmdesc)
|
||||
const VMStateField *field, JSONWriter *vmdesc)
|
||||
{
|
||||
SPARCCPU *cpu = opaque;
|
||||
CPUSPARCState *env = &cpu->env;
|
||||
|
@ -35,17 +35,15 @@ static QString *from_json_str(const char *jstr, bool single, Error **errp)
|
||||
|
||||
static char *to_json_str(QString *str)
|
||||
{
|
||||
QString *json = qobject_to_json(QOBJECT(str));
|
||||
char *jstr;
|
||||
GString *json = qobject_to_json(QOBJECT(str));
|
||||
|
||||
if (!json) {
|
||||
return NULL;
|
||||
}
|
||||
/* peel off double quotes */
|
||||
jstr = g_strndup(qstring_get_str(json) + 1,
|
||||
qstring_get_length(json) - 2);
|
||||
qobject_unref(json);
|
||||
return jstr;
|
||||
g_string_truncate(json, json->len - 1);
|
||||
g_string_erase(json, 0, 1);
|
||||
return g_string_free(json, false);
|
||||
}
|
||||
|
||||
static void escaped_string(void)
|
||||
@ -91,7 +89,7 @@ static void escaped_string(void)
|
||||
for (j = 0; j < 2; j++) {
|
||||
if (test_cases[i].utf8_out) {
|
||||
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);
|
||||
if (!test_cases[i].skip) {
|
||||
jstr = to_json_str(cstr);
|
||||
@ -753,7 +751,7 @@ static void utf8_string(void)
|
||||
/* Parse @json_in, expect @utf8_out */
|
||||
if (utf8_out) {
|
||||
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);
|
||||
} else {
|
||||
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 */
|
||||
if (!strstr(json_out, "\\uFFFD")) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void simple_number(void)
|
||||
static void int_number(void)
|
||||
{
|
||||
int i;
|
||||
struct {
|
||||
const char *encoded;
|
||||
int64_t decoded;
|
||||
int skip;
|
||||
const char *reencoded;
|
||||
} test_cases[] = {
|
||||
{ "0", 0 },
|
||||
{ "1234", 1234 },
|
||||
{ "1", 1 },
|
||||
{ "-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++) {
|
||||
QNum *qnum;
|
||||
int64_t val;
|
||||
|
||||
qnum = qobject_to(QNum,
|
||||
qobject_from_json(test_cases[i].encoded,
|
||||
&error_abort));
|
||||
g_assert(qnum);
|
||||
g_assert(qnum_get_try_int(qnum, &val));
|
||||
g_assert_cmpint(val, ==, test_cases[i].decoded);
|
||||
if (test_cases[i].skip == 0) {
|
||||
QString *str;
|
||||
|
||||
str = qobject_to_json(QOBJECT(qnum));
|
||||
g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
|
||||
qobject_unref(str);
|
||||
g_assert(qnum_get_try_int(qnum, &ival));
|
||||
g_assert_cmpint(ival, ==, test_cases[i].decoded);
|
||||
if (test_cases[i].decoded >= 0) {
|
||||
g_assert(qnum_get_try_uint(qnum, &uval));
|
||||
g_assert_cmpuint(uval, ==, (uint64_t)test_cases[i].decoded);
|
||||
} else {
|
||||
g_assert(!qnum_get_try_uint(qnum, &uval));
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
static void large_number(void)
|
||||
static void uint_number(void)
|
||||
{
|
||||
const char *maxu64 = "18446744073709551615"; /* 2^64-1 */
|
||||
const char *gtu64 = "18446744073709551616"; /* 2^64 */
|
||||
const char *lti64 = "-9223372036854775809"; /* -2^63 - 1 */
|
||||
struct {
|
||||
const char *encoded;
|
||||
uint64_t decoded;
|
||||
const char *reencoded;
|
||||
} test_cases[] = {
|
||||
{ "9223372036854775808", (uint64_t)1 << 63 },
|
||||
{ "18446744073709551615", UINT64_MAX },
|
||||
{},
|
||||
};
|
||||
int i;
|
||||
QNum *qnum;
|
||||
QString *str;
|
||||
uint64_t val;
|
||||
int64_t ival;
|
||||
uint64_t uval;
|
||||
GString *str;
|
||||
|
||||
qnum = qobject_to(QNum, qobject_from_json(maxu64, &error_abort));
|
||||
g_assert(qnum);
|
||||
g_assert_cmpuint(qnum_get_uint(qnum), ==, 18446744073709551615U);
|
||||
g_assert(!qnum_get_try_int(qnum, &ival));
|
||||
for (i = 0; test_cases[i].encoded; i++) {
|
||||
qnum = qobject_to(QNum,
|
||||
qobject_from_json(test_cases[i].encoded,
|
||||
&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));
|
||||
g_assert_cmpstr(qstring_get_str(str), ==, maxu64);
|
||||
qobject_unref(str);
|
||||
qobject_unref(qnum);
|
||||
str = qobject_to_json(QOBJECT(qnum));
|
||||
g_assert_cmpstr(str->str, ==,
|
||||
test_cases[i].reencoded ?: test_cases[i].encoded);
|
||||
g_string_free(str, true);
|
||||
|
||||
qnum = qobject_to(QNum, qobject_from_json(gtu64, &error_abort));
|
||||
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);
|
||||
qobject_unref(qnum);
|
||||
}
|
||||
}
|
||||
|
||||
static void float_number(void)
|
||||
{
|
||||
int i;
|
||||
struct {
|
||||
const char *encoded;
|
||||
double decoded;
|
||||
int skip;
|
||||
const char *reencoded;
|
||||
} test_cases[] = {
|
||||
{ "32.43", 32.43 },
|
||||
{ "0.222", 0.222 },
|
||||
{ "-32.12313", -32.12313 },
|
||||
{ "-32.20e-10", -32.20e-10, .skip = 1 },
|
||||
{ },
|
||||
{ "-32.12313", -32.12313, "-32.123130000000003" },
|
||||
{ "-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++) {
|
||||
QObject *obj;
|
||||
QNum *qnum;
|
||||
|
||||
obj = qobject_from_json(test_cases[i].encoded, &error_abort);
|
||||
qnum = qobject_to(QNum, obj);
|
||||
qnum = qobject_to(QNum,
|
||||
qobject_from_json(test_cases[i].encoded,
|
||||
&error_abort));
|
||||
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) {
|
||||
QString *str;
|
||||
|
||||
str = qobject_to_json(obj);
|
||||
g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
|
||||
qobject_unref(str);
|
||||
}
|
||||
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);
|
||||
}
|
||||
@ -913,7 +915,7 @@ static void keyword_literal(void)
|
||||
QObject *obj;
|
||||
QBool *qbool;
|
||||
QNull *null;
|
||||
QString *str;
|
||||
GString *str;
|
||||
|
||||
obj = qobject_from_json("true", &error_abort);
|
||||
qbool = qobject_to(QBool, obj);
|
||||
@ -921,8 +923,8 @@ static void keyword_literal(void)
|
||||
g_assert(qbool_get_bool(qbool) == true);
|
||||
|
||||
str = qobject_to_json(obj);
|
||||
g_assert(strcmp(qstring_get_str(str), "true") == 0);
|
||||
qobject_unref(str);
|
||||
g_assert_cmpstr(str->str, ==, "true");
|
||||
g_string_free(str, true);
|
||||
|
||||
qobject_unref(qbool);
|
||||
|
||||
@ -932,8 +934,8 @@ static void keyword_literal(void)
|
||||
g_assert(qbool_get_bool(qbool) == false);
|
||||
|
||||
str = qobject_to_json(obj);
|
||||
g_assert(strcmp(qstring_get_str(str), "false") == 0);
|
||||
qobject_unref(str);
|
||||
g_assert_cmpstr(str->str, ==, "false");
|
||||
g_string_free(str, true);
|
||||
|
||||
qobject_unref(qbool);
|
||||
|
||||
@ -1019,9 +1021,8 @@ static void interpolation_valid(void)
|
||||
|
||||
/* string */
|
||||
|
||||
qstr = qobject_to(QString,
|
||||
qobject_from_jsonf_nofail("%s", value_s));
|
||||
g_assert_cmpstr(qstring_get_try_str(qstr), ==, value_s);
|
||||
qstr = qobject_to(QString, qobject_from_jsonf_nofail("%s", value_s));
|
||||
g_assert_cmpstr(qstring_get_str(qstr), ==, value_s);
|
||||
qobject_unref(qstr);
|
||||
|
||||
/* object */
|
||||
@ -1083,7 +1084,7 @@ static void simple_dict(void)
|
||||
|
||||
for (i = 0; test_cases[i].encoded; i++) {
|
||||
QObject *obj;
|
||||
QString *str;
|
||||
GString *str;
|
||||
|
||||
obj = qobject_from_json(test_cases[i].encoded, &error_abort);
|
||||
g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
|
||||
@ -1091,10 +1092,10 @@ static void simple_dict(void)
|
||||
str = qobject_to_json(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));
|
||||
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++) {
|
||||
QObject *obj;
|
||||
QString *str;
|
||||
GString *str;
|
||||
|
||||
obj = qobject_from_json(test_cases[i].encoded, &error_abort);
|
||||
g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
|
||||
@ -1200,10 +1201,10 @@ static void simple_list(void)
|
||||
str = qobject_to_json(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));
|
||||
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++) {
|
||||
QObject *obj;
|
||||
QString *str;
|
||||
GString *str;
|
||||
|
||||
obj = qobject_from_json(test_cases[i].encoded, &error_abort);
|
||||
g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
|
||||
@ -1262,11 +1263,11 @@ static void simple_whitespace(void)
|
||||
str = qobject_to_json(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));
|
||||
|
||||
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/utf8", utf8_string);
|
||||
|
||||
g_test_add_func("/literals/number/simple", simple_number);
|
||||
g_test_add_func("/literals/number/large", large_number);
|
||||
g_test_add_func("/literals/number/int", int_number);
|
||||
g_test_add_func("/literals/number/uint", uint_number);
|
||||
g_test_add_func("/literals/number/float", float_number);
|
||||
|
||||
g_test_add_func("/literals/keyword", keyword_literal);
|
||||
|
@ -147,7 +147,13 @@ static void qnum_to_string_test(void)
|
||||
|
||||
qn = qnum_from_double(0.42);
|
||||
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);
|
||||
qobject_unref(qn);
|
||||
}
|
||||
|
@ -155,8 +155,7 @@ static void qobject_is_equal_string_test(void)
|
||||
str_case = qstring_from_str("Foo");
|
||||
|
||||
/* Should yield "foo" */
|
||||
str_built = qstring_from_substr("form", 0, 2);
|
||||
qstring_append_chr(str_built, 'o');
|
||||
str_built = qstring_from_substr("buffoon", 3, 6);
|
||||
|
||||
check_unequal(str_base, str_whitespace_0, str_whitespace_1,
|
||||
str_whitespace_2, str_whitespace_3, str_case);
|
||||
|
@ -47,21 +47,6 @@ static void qstring_get_str_test(void)
|
||||
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)
|
||||
{
|
||||
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/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/to_qstring", qobject_to_qstring_test);
|
||||
|
||||
|
@ -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. */
|
||||
if (qobj) {
|
||||
int log = getenv("QTEST_LOG") != NULL;
|
||||
QString *qstr = qobject_to_json(qobj);
|
||||
const char *str;
|
||||
GString *str = qobject_to_json(qobj);
|
||||
|
||||
/*
|
||||
* BUG: QMP doesn't react to input until it sees a newline, an
|
||||
* object, or an array. Work-around: give it a newline.
|
||||
*/
|
||||
qstring_append_chr(qstr, '\n');
|
||||
str = qstring_get_str(qstr);
|
||||
g_string_append_c(str, '\n');
|
||||
|
||||
if (log) {
|
||||
fprintf(stderr, "%s", str);
|
||||
fprintf(stderr, "%s", str->str);
|
||||
}
|
||||
/* Send QMP request */
|
||||
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 {
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -1197,9 +1195,9 @@ void qtest_qmp_assert_success(QTestState *qts, const char *fmt, ...)
|
||||
|
||||
g_assert(response);
|
||||
if (!qdict_haskey(response, "return")) {
|
||||
QString *s = qobject_to_json_pretty(QOBJECT(response));
|
||||
g_test_message("%s", qstring_get_str(s));
|
||||
qobject_unref(s);
|
||||
GString *s = qobject_to_json_pretty(QOBJECT(response), true);
|
||||
g_test_message("%s", s->str);
|
||||
g_string_free(s, true);
|
||||
}
|
||||
g_assert(qdict_haskey(response, "return"));
|
||||
qobject_unref(response);
|
||||
|
@ -65,16 +65,13 @@ static void test_clone_alternate(void)
|
||||
|
||||
static void test_clone_list_union(void)
|
||||
{
|
||||
uint8List *src, *dst;
|
||||
uint8List *src = NULL, *dst;
|
||||
uint8List *tmp = NULL;
|
||||
int i;
|
||||
|
||||
/* Build list in reverse */
|
||||
for (i = 10; i; i--) {
|
||||
src = g_new0(uint8List, 1);
|
||||
src->next = tmp;
|
||||
src->value = i;
|
||||
tmp = src;
|
||||
QAPI_LIST_PREPEND(src, i);
|
||||
}
|
||||
|
||||
dst = QAPI_CLONE(uint8List, src);
|
||||
|
@ -223,7 +223,8 @@ static void test_visitor_out_list(TestOutputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
const char *value_str = "list value";
|
||||
TestStructList *p, *head = NULL;
|
||||
TestStruct *value;
|
||||
TestStructList *head = NULL;
|
||||
const int max_items = 10;
|
||||
bool value_bool = true;
|
||||
int value_int = 10;
|
||||
@ -233,14 +234,12 @@ static void test_visitor_out_list(TestOutputVisitorData *data,
|
||||
|
||||
/* Build the list in reverse order... */
|
||||
for (i = 0; i < max_items; i++) {
|
||||
p = g_malloc0(sizeof(*p));
|
||||
p->value = g_malloc0(sizeof(*p->value));
|
||||
p->value->integer = value_int + (max_items - i - 1);
|
||||
p->value->boolean = value_bool;
|
||||
p->value->string = g_strdup(value_str);
|
||||
value = g_malloc0(sizeof(*value));
|
||||
value->integer = value_int + (max_items - i - 1);
|
||||
value->boolean = value_bool;
|
||||
value->string = g_strdup(value_str);
|
||||
|
||||
p->next = head;
|
||||
head = p;
|
||||
QAPI_LIST_PREPEND(head, value);
|
||||
}
|
||||
|
||||
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,
|
||||
const void *unused)
|
||||
{
|
||||
UserDefTwoList *p, *head = NULL;
|
||||
UserDefTwo *value;
|
||||
UserDefTwoList *head = NULL;
|
||||
const char string[] = "foo bar";
|
||||
int i, max_count = 1024;
|
||||
|
||||
for (i = 0; i < max_count; i++) {
|
||||
p = g_malloc0(sizeof(*p));
|
||||
p->value = g_malloc0(sizeof(*p->value));
|
||||
value = g_malloc0(sizeof(*value));
|
||||
|
||||
p->value->string0 = g_strdup(string);
|
||||
p->value->dict1 = g_new0(UserDefTwoDict, 1);
|
||||
p->value->dict1->string1 = g_strdup(string);
|
||||
p->value->dict1->dict2 = g_new0(UserDefTwoDictDict, 1);
|
||||
p->value->dict1->dict2->userdef = g_new0(UserDefOne, 1);
|
||||
p->value->dict1->dict2->userdef->string = g_strdup(string);
|
||||
p->value->dict1->dict2->userdef->integer = 42;
|
||||
p->value->dict1->dict2->string = g_strdup(string);
|
||||
p->value->dict1->has_dict3 = false;
|
||||
value->string0 = g_strdup(string);
|
||||
value->dict1 = g_new0(UserDefTwoDict, 1);
|
||||
value->dict1->string1 = g_strdup(string);
|
||||
value->dict1->dict2 = g_new0(UserDefTwoDictDict, 1);
|
||||
value->dict1->dict2->userdef = g_new0(UserDefOne, 1);
|
||||
value->dict1->dict2->userdef->string = g_strdup(string);
|
||||
value->dict1->dict2->userdef->integer = 42;
|
||||
value->dict1->dict2->string = g_strdup(string);
|
||||
value->dict1->has_dict3 = false;
|
||||
|
||||
p->next = head;
|
||||
head = p;
|
||||
QAPI_LIST_PREPEND(head, value);
|
||||
}
|
||||
|
||||
qapi_free_UserDefTwoList(head);
|
||||
|
@ -130,13 +130,13 @@ static void test_visitor_out_bool(TestOutputVisitorData *data,
|
||||
static void test_visitor_out_number(TestOutputVisitorData *data,
|
||||
const void *unused)
|
||||
{
|
||||
double value = 3.14;
|
||||
double value = 3.1415926535897932;
|
||||
char *str;
|
||||
|
||||
visit_type_number(data->ov, NULL, &value, &error_abort);
|
||||
|
||||
str = visitor_get(data);
|
||||
g_assert_cmpstr(str, ==, "3.140000");
|
||||
g_assert_cmpstr(str, ==, "3.1415926535897931");
|
||||
}
|
||||
|
||||
static void test_visitor_out_string(TestOutputVisitorData *data,
|
||||
|
@ -55,7 +55,6 @@ typedef struct PrimitiveType {
|
||||
int16_t s16;
|
||||
int32_t s32;
|
||||
int64_t s64;
|
||||
intmax_t max;
|
||||
} value;
|
||||
enum PrimitiveTypeKind type;
|
||||
const char *description;
|
||||
@ -307,25 +306,46 @@ static void test_primitives(gconstpointer opaque)
|
||||
&error_abort);
|
||||
|
||||
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_free((char *)pt_copy->value.string);
|
||||
} else if (pt->type == PTYPE_NUMBER) {
|
||||
GString *double_expected = g_string_new("");
|
||||
GString *double_actual = g_string_new("");
|
||||
/* we serialize with %f for our reference visitors, so rather than fuzzy
|
||||
* floating math to test "equality", just compare the formatted values
|
||||
*/
|
||||
g_string_printf(double_expected, "%.6f", pt->value.number);
|
||||
g_string_printf(double_actual, "%.6f", pt_copy->value.number);
|
||||
g_assert_cmpstr(double_actual->str, ==, double_expected->str);
|
||||
|
||||
g_string_free(double_expected, true);
|
||||
g_string_free(double_actual, true);
|
||||
} else if (pt->type == PTYPE_BOOLEAN) {
|
||||
g_assert_cmpint(!!pt->value.max, ==, !!pt->value.max);
|
||||
} else {
|
||||
g_assert_cmpint(pt->value.max, ==, pt_copy->value.max);
|
||||
break;
|
||||
case PTYPE_BOOLEAN:
|
||||
g_assert_cmpint(pt->value.boolean, ==, pt->value.boolean);
|
||||
break;
|
||||
case PTYPE_NUMBER:
|
||||
g_assert_cmpfloat(pt->value.number, ==, pt_copy->value.number);
|
||||
break;
|
||||
case PTYPE_INTEGER:
|
||||
g_assert_cmpint(pt->value.integer, ==, pt_copy->value.integer);
|
||||
break;
|
||||
case PTYPE_U8:
|
||||
g_assert_cmpuint(pt->value.u8, ==, pt_copy->value.u8);
|
||||
break;
|
||||
case PTYPE_U16:
|
||||
g_assert_cmpuint(pt->value.u16, ==, pt_copy->value.u16);
|
||||
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);
|
||||
@ -351,135 +371,51 @@ static void test_primitive_lists(gconstpointer opaque)
|
||||
for (i = 0; i < 32; i++) {
|
||||
switch (pl.type) {
|
||||
case PTYPE_STRING: {
|
||||
strList *tmp = g_new0(strList, 1);
|
||||
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;
|
||||
}
|
||||
QAPI_LIST_PREPEND(pl.value.strings, g_strdup(pt->value.string));
|
||||
break;
|
||||
}
|
||||
case PTYPE_INTEGER: {
|
||||
intList *tmp = g_new0(intList, 1);
|
||||
tmp->value = pt->value.integer;
|
||||
if (pl.value.integers == NULL) {
|
||||
pl.value.integers = tmp;
|
||||
} else {
|
||||
tmp->next = pl.value.integers;
|
||||
pl.value.integers = tmp;
|
||||
}
|
||||
QAPI_LIST_PREPEND(pl.value.integers, pt->value.integer);
|
||||
break;
|
||||
}
|
||||
case PTYPE_S8: {
|
||||
int8List *tmp = g_new0(int8List, 1);
|
||||
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;
|
||||
}
|
||||
QAPI_LIST_PREPEND(pl.value.s8_integers, pt->value.s8);
|
||||
break;
|
||||
}
|
||||
case PTYPE_S16: {
|
||||
int16List *tmp = g_new0(int16List, 1);
|
||||
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;
|
||||
}
|
||||
QAPI_LIST_PREPEND(pl.value.s16_integers, pt->value.s16);
|
||||
break;
|
||||
}
|
||||
case PTYPE_S32: {
|
||||
int32List *tmp = g_new0(int32List, 1);
|
||||
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;
|
||||
}
|
||||
QAPI_LIST_PREPEND(pl.value.s32_integers, pt->value.s32);
|
||||
break;
|
||||
}
|
||||
case PTYPE_S64: {
|
||||
int64List *tmp = g_new0(int64List, 1);
|
||||
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;
|
||||
}
|
||||
QAPI_LIST_PREPEND(pl.value.s64_integers, pt->value.s64);
|
||||
break;
|
||||
}
|
||||
case PTYPE_U8: {
|
||||
uint8List *tmp = g_new0(uint8List, 1);
|
||||
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;
|
||||
}
|
||||
QAPI_LIST_PREPEND(pl.value.u8_integers, pt->value.u8);
|
||||
break;
|
||||
}
|
||||
case PTYPE_U16: {
|
||||
uint16List *tmp = g_new0(uint16List, 1);
|
||||
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;
|
||||
}
|
||||
QAPI_LIST_PREPEND(pl.value.u16_integers, pt->value.u16);
|
||||
break;
|
||||
}
|
||||
case PTYPE_U32: {
|
||||
uint32List *tmp = g_new0(uint32List, 1);
|
||||
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;
|
||||
}
|
||||
QAPI_LIST_PREPEND(pl.value.u32_integers, pt->value.u32);
|
||||
break;
|
||||
}
|
||||
case PTYPE_U64: {
|
||||
uint64List *tmp = g_new0(uint64List, 1);
|
||||
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;
|
||||
}
|
||||
QAPI_LIST_PREPEND(pl.value.u64_integers, pt->value.u64);
|
||||
break;
|
||||
}
|
||||
case PTYPE_NUMBER: {
|
||||
numberList *tmp = g_new0(numberList, 1);
|
||||
tmp->value = pt->value.number;
|
||||
if (pl.value.numbers == NULL) {
|
||||
pl.value.numbers = tmp;
|
||||
} else {
|
||||
tmp->next = pl.value.numbers;
|
||||
pl.value.numbers = tmp;
|
||||
}
|
||||
QAPI_LIST_PREPEND(pl.value.numbers, pt->value.number);
|
||||
break;
|
||||
}
|
||||
case PTYPE_BOOLEAN: {
|
||||
boolList *tmp = g_new0(boolList, 1);
|
||||
tmp->value = pt->value.boolean;
|
||||
if (pl.value.booleans == NULL) {
|
||||
pl.value.booleans = tmp;
|
||||
} else {
|
||||
tmp->next = pl.value.booleans;
|
||||
pl.value.booleans = tmp;
|
||||
}
|
||||
QAPI_LIST_PREPEND(pl.value.booleans, pt->value.boolean);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -704,10 +640,7 @@ static void test_nested_struct_list(gconstpointer opaque)
|
||||
int i = 0;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
tmp = g_new0(UserDefTwoList, 1);
|
||||
tmp->value = nested_struct_create();
|
||||
tmp->next = listp;
|
||||
listp = tmp;
|
||||
QAPI_LIST_PREPEND(listp, nested_struct_create());
|
||||
}
|
||||
|
||||
ops->serialize(listp, &serialize_data, visit_nested_struct_list,
|
||||
@ -790,10 +723,6 @@ static PrimitiveType pt_values[] = {
|
||||
.value.boolean = 0,
|
||||
},
|
||||
/* 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",
|
||||
.type = PTYPE_NUMBER,
|
||||
@ -802,7 +731,7 @@ static PrimitiveType pt_values[] = {
|
||||
{
|
||||
.description = "number_sanity2",
|
||||
.type = PTYPE_NUMBER,
|
||||
.value.number = 3.14159265,
|
||||
.value.number = 3.141593,
|
||||
},
|
||||
{
|
||||
.description = "number_min",
|
||||
@ -1028,15 +957,15 @@ static void qmp_deserialize(void **native_out, void *datap,
|
||||
VisitorFunc visit, Error **errp)
|
||||
{
|
||||
QmpSerializeData *d = datap;
|
||||
QString *output_json;
|
||||
GString *output_json;
|
||||
QObject *obj_orig, *obj;
|
||||
|
||||
visit_complete(d->qov, &d->obj);
|
||||
obj_orig = d->obj;
|
||||
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);
|
||||
qobject_unref(obj_orig);
|
||||
qobject_unref(obj);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user