qemu/qom/object.c
<<
>>
Prefs
   1/*
   2 * QEMU Object Model
   3 *
   4 * Copyright IBM, Corp. 2011
   5 *
   6 * Authors:
   7 *  Anthony Liguori   <aliguori@us.ibm.com>
   8 *
   9 * This work is licensed under the terms of the GNU GPL, version 2 or later.
  10 * See the COPYING file in the top-level directory.
  11 */
  12
  13#include "qemu/osdep.h"
  14#include "hw/qdev-core.h"
  15#include "qapi/error.h"
  16#include "qom/object.h"
  17#include "qom/object_interfaces.h"
  18#include "qemu/cutils.h"
  19#include "qemu/memalign.h"
  20#include "qapi/visitor.h"
  21#include "qapi/string-input-visitor.h"
  22#include "qapi/string-output-visitor.h"
  23#include "qapi/qobject-input-visitor.h"
  24#include "qapi/forward-visitor.h"
  25#include "qapi/qapi-builtin-visit.h"
  26#include "qobject/qjson.h"
  27#include "trace.h"
  28
  29/* TODO: replace QObject with a simpler visitor to avoid a dependency
  30 * of the QOM core on QObject?  */
  31#include "qom/qom-qobject.h"
  32#include "qobject/qbool.h"
  33#include "qobject/qlist.h"
  34#include "qobject/qnum.h"
  35#include "qobject/qstring.h"
  36#include "qemu/error-report.h"
  37
  38#define MAX_INTERFACES 32
  39
  40typedef struct InterfaceImpl InterfaceImpl;
  41typedef struct TypeImpl TypeImpl;
  42
  43struct InterfaceImpl
  44{
  45    const char *typename;
  46};
  47
  48struct TypeImpl
  49{
  50    const char *name;
  51
  52    size_t class_size;
  53
  54    size_t instance_size;
  55    size_t instance_align;
  56
  57    void (*class_init)(ObjectClass *klass, const void *data);
  58    void (*class_base_init)(ObjectClass *klass, const void *data);
  59
  60    const void *class_data;
  61
  62    void (*instance_init)(Object *obj);
  63    void (*instance_post_init)(Object *obj);
  64    void (*instance_finalize)(Object *obj);
  65
  66    bool abstract;
  67
  68    const char *parent;
  69    TypeImpl *parent_type;
  70
  71    ObjectClass *class;
  72
  73    int num_interfaces;
  74    InterfaceImpl interfaces[MAX_INTERFACES];
  75};
  76
  77static Type type_interface;
  78
  79static GHashTable *type_table_get(void)
  80{
  81    static GHashTable *type_table;
  82
  83    if (type_table == NULL) {
  84        type_table = g_hash_table_new(g_str_hash, g_str_equal);
  85    }
  86
  87    return type_table;
  88}
  89
  90static bool enumerating_types;
  91
  92static void type_table_add(TypeImpl *ti)
  93{
  94    assert(!enumerating_types);
  95    g_hash_table_insert(type_table_get(), (void *)ti->name, ti);
  96}
  97
  98static TypeImpl *type_table_lookup(const char *name)
  99{
 100    return g_hash_table_lookup(type_table_get(), name);
 101}
 102
 103static TypeImpl *type_new(const TypeInfo *info)
 104{
 105    TypeImpl *ti = g_malloc0(sizeof(*ti));
 106    int i;
 107
 108    g_assert(info->name != NULL);
 109
 110    if (type_table_lookup(info->name) != NULL) {
 111        fprintf(stderr, "Registering `%s' which already exists\n", info->name);
 112        abort();
 113    }
 114
 115    ti->name = g_strdup(info->name);
 116    ti->parent = g_strdup(info->parent);
 117
 118    ti->class_size = info->class_size;
 119    ti->instance_size = info->instance_size;
 120    ti->instance_align = info->instance_align;
 121
 122    ti->class_init = info->class_init;
 123    ti->class_base_init = info->class_base_init;
 124    ti->class_data = info->class_data;
 125
 126    ti->instance_init = info->instance_init;
 127    ti->instance_post_init = info->instance_post_init;
 128    ti->instance_finalize = info->instance_finalize;
 129
 130    ti->abstract = info->abstract;
 131
 132    for (i = 0; info->interfaces && info->interfaces[i].type; i++) {
 133        ti->interfaces[i].typename = g_strdup(info->interfaces[i].type);
 134    }
 135    ti->num_interfaces = i;
 136
 137    return ti;
 138}
 139
 140static bool type_name_is_valid(const char *name)
 141{
 142    const int slen = strlen(name);
 143    int plen;
 144
 145    g_assert(slen > 1);
 146
 147    /*
 148     * Ideally, the name should start with a letter - however, we've got
 149     * too many names starting with a digit already, so allow digits here,
 150     * too (except '0' which is not used yet)
 151     */
 152    if (!g_ascii_isalnum(name[0]) || name[0] == '0') {
 153        return false;
 154    }
 155
 156    plen = strspn(name, "abcdefghijklmnopqrstuvwxyz"
 157                        "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
 158                        "0123456789-_.");
 159
 160    return plen == slen;
 161}
 162
 163static TypeImpl *type_register_internal(const TypeInfo *info)
 164{
 165    TypeImpl *ti;
 166
 167    if (!type_name_is_valid(info->name)) {
 168        fprintf(stderr, "Registering '%s' with illegal type name\n", info->name);
 169        abort();
 170    }
 171
 172    ti = type_new(info);
 173
 174    type_table_add(ti);
 175    return ti;
 176}
 177
 178TypeImpl *type_register_static(const TypeInfo *info)
 179{
 180    assert(info->parent);
 181    return type_register_internal(info);
 182}
 183
 184void type_register_static_array(const TypeInfo *infos, int nr_infos)
 185{
 186    int i;
 187
 188    for (i = 0; i < nr_infos; i++) {
 189        type_register_static(&infos[i]);
 190    }
 191}
 192
 193static TypeImpl *type_get_by_name_noload(const char *name)
 194{
 195    if (name == NULL) {
 196        return NULL;
 197    }
 198
 199    return type_table_lookup(name);
 200}
 201
 202static TypeImpl *type_get_or_load_by_name(const char *name, Error **errp)
 203{
 204    TypeImpl *type = type_get_by_name_noload(name);
 205
 206#ifdef CONFIG_MODULES
 207    if (!type) {
 208        int rv = module_load_qom(name, errp);
 209        if (rv > 0) {
 210            type = type_get_by_name_noload(name);
 211        } else {
 212            error_prepend(errp, "could not load a module for type '%s'", name);
 213            return NULL;
 214        }
 215    }
 216#endif
 217    if (!type) {
 218        error_setg(errp, "unknown type '%s'", name);
 219    }
 220
 221    return type;
 222}
 223
 224static TypeImpl *type_get_parent(TypeImpl *type)
 225{
 226    if (!type->parent_type && type->parent) {
 227        type->parent_type = type_get_by_name_noload(type->parent);
 228        if (!type->parent_type) {
 229            fprintf(stderr, "Type '%s' is missing its parent '%s'\n",
 230                    type->name, type->parent);
 231            abort();
 232        }
 233    }
 234
 235    return type->parent_type;
 236}
 237
 238static bool type_has_parent(TypeImpl *type)
 239{
 240    return (type->parent != NULL);
 241}
 242
 243static size_t type_class_get_size(TypeImpl *ti)
 244{
 245    if (ti->class_size) {
 246        return ti->class_size;
 247    }
 248
 249    if (type_has_parent(ti)) {
 250        return type_class_get_size(type_get_parent(ti));
 251    }
 252
 253    return sizeof(ObjectClass);
 254}
 255
 256static size_t type_object_get_size(TypeImpl *ti)
 257{
 258    if (ti->instance_size) {
 259        return ti->instance_size;
 260    }
 261
 262    if (type_has_parent(ti)) {
 263        return type_object_get_size(type_get_parent(ti));
 264    }
 265
 266    return 0;
 267}
 268
 269static size_t type_object_get_align(TypeImpl *ti)
 270{
 271    if (ti->instance_align) {
 272        return ti->instance_align;
 273    }
 274
 275    if (type_has_parent(ti)) {
 276        return type_object_get_align(type_get_parent(ti));
 277    }
 278
 279    return 0;
 280}
 281
 282static bool type_is_ancestor(TypeImpl *type, TypeImpl *target_type)
 283{
 284    assert(target_type);
 285
 286    /* Check if target_type is a direct ancestor of type */
 287    while (type) {
 288        if (type == target_type) {
 289            return true;
 290        }
 291
 292        type = type_get_parent(type);
 293    }
 294
 295    return false;
 296}
 297
 298static void type_initialize(TypeImpl *ti);
 299
 300static void type_initialize_interface(TypeImpl *ti, TypeImpl *interface_type,
 301                                      TypeImpl *parent_type)
 302{
 303    InterfaceClass *new_iface;
 304    TypeInfo info = { };
 305    TypeImpl *iface_impl;
 306
 307    info.parent = parent_type->name;
 308    info.name = g_strdup_printf("%s::%s", ti->name, interface_type->name);
 309    info.abstract = true;
 310
 311    iface_impl = type_new(&info);
 312    iface_impl->parent_type = parent_type;
 313    type_initialize(iface_impl);
 314    g_free((char *)info.name);
 315
 316    new_iface = (InterfaceClass *)iface_impl->class;
 317    new_iface->interface_type = interface_type;
 318
 319    ti->class->interfaces = g_slist_append(ti->class->interfaces, new_iface);
 320}
 321
 322static void object_property_free(gpointer data)
 323{
 324    ObjectProperty *prop = data;
 325
 326    if (prop->defval) {
 327        qobject_unref(prop->defval);
 328        prop->defval = NULL;
 329    }
 330    g_free(prop->name);
 331    g_free(prop->type);
 332    g_free(prop->description);
 333    g_free(prop);
 334}
 335
 336static void type_initialize(TypeImpl *ti)
 337{
 338    TypeImpl *parent;
 339
 340    if (ti->class) {
 341        return;
 342    }
 343
 344    ti->class_size = type_class_get_size(ti);
 345    ti->instance_size = type_object_get_size(ti);
 346    ti->instance_align = type_object_get_align(ti);
 347    /* Any type with zero instance_size is implicitly abstract.
 348     * This means interface types are all abstract.
 349     */
 350    if (ti->instance_size == 0) {
 351        ti->abstract = true;
 352    }
 353    if (type_is_ancestor(ti, type_interface)) {
 354        assert(ti->instance_size == 0);
 355        assert(ti->abstract);
 356        assert(!ti->instance_init);
 357        assert(!ti->instance_post_init);
 358        assert(!ti->instance_finalize);
 359        assert(!ti->num_interfaces);
 360    }
 361    ti->class = g_malloc0(ti->class_size);
 362
 363    parent = type_get_parent(ti);
 364    if (parent) {
 365        type_initialize(parent);
 366        GSList *e;
 367        int i;
 368
 369        g_assert(parent->class_size <= ti->class_size);
 370        g_assert(parent->instance_size <= ti->instance_size);
 371        memcpy(ti->class, parent->class, parent->class_size);
 372        ti->class->interfaces = NULL;
 373
 374        for (e = parent->class->interfaces; e; e = e->next) {
 375            InterfaceClass *iface = e->data;
 376            ObjectClass *klass = OBJECT_CLASS(iface);
 377
 378            type_initialize_interface(ti, iface->interface_type, klass->type);
 379        }
 380
 381        for (i = 0; i < ti->num_interfaces; i++) {
 382            TypeImpl *t = type_get_by_name_noload(ti->interfaces[i].typename);
 383            if (!t) {
 384                error_report("missing interface '%s' for object '%s'",
 385                             ti->interfaces[i].typename, parent->name);
 386                abort();
 387            }
 388            for (e = ti->class->interfaces; e; e = e->next) {
 389                TypeImpl *target_type = OBJECT_CLASS(e->data)->type;
 390
 391                if (type_is_ancestor(target_type, t)) {
 392                    break;
 393                }
 394            }
 395
 396            if (e) {
 397                continue;
 398            }
 399
 400            type_initialize_interface(ti, t, t);
 401        }
 402    }
 403
 404    ti->class->properties = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
 405                                                  object_property_free);
 406
 407    ti->class->type = ti;
 408
 409    while (parent) {
 410        if (parent->class_base_init) {
 411            parent->class_base_init(ti->class, ti->class_data);
 412        }
 413        parent = type_get_parent(parent);
 414    }
 415
 416    if (ti->class_init) {
 417        ti->class_init(ti->class, ti->class_data);
 418    }
 419}
 420
 421static void object_init_with_type(Object *obj, TypeImpl *ti)
 422{
 423    if (type_has_parent(ti)) {
 424        object_init_with_type(obj, type_get_parent(ti));
 425    }
 426
 427    if (ti->instance_init) {
 428        ti->instance_init(obj);
 429    }
 430}
 431
 432static void object_post_init_with_type(Object *obj, TypeImpl *ti)
 433{
 434    if (type_has_parent(ti)) {
 435        object_post_init_with_type(obj, type_get_parent(ti));
 436    }
 437
 438    if (ti->instance_post_init) {
 439        ti->instance_post_init(obj);
 440    }
 441}
 442
 443bool object_apply_global_props(Object *obj, const GPtrArray *props,
 444                               Error **errp)
 445{
 446    int i;
 447
 448    if (!props) {
 449        return true;
 450    }
 451
 452    for (i = 0; i < props->len; i++) {
 453        GlobalProperty *p = g_ptr_array_index(props, i);
 454        Error *err = NULL;
 455
 456        if (object_dynamic_cast(obj, p->driver) == NULL) {
 457            continue;
 458        }
 459        if (p->optional && !object_property_find(obj, p->property)) {
 460            continue;
 461        }
 462        p->used = true;
 463        if (!object_property_parse(obj, p->property, p->value, &err)) {
 464            error_prepend(&err, "can't apply global %s.%s=%s: ",
 465                          p->driver, p->property, p->value);
 466            /*
 467             * If errp != NULL, propagate error and return.
 468             * If errp == NULL, report a warning, but keep going
 469             * with the remaining globals.
 470             */
 471            if (errp) {
 472                error_propagate(errp, err);
 473                return false;
 474            } else {
 475                warn_report_err(err);
 476            }
 477        }
 478    }
 479
 480    return true;
 481}
 482
 483/*
 484 * Global property defaults
 485 * Slot 0: accelerator's global property defaults
 486 * Slot 1: machine's global property defaults
 487 * Slot 2: global properties from legacy command line option
 488 * Each is a GPtrArray of GlobalProperty.
 489 * Applied in order, later entries override earlier ones.
 490 */
 491static GPtrArray *object_compat_props[3];
 492
 493/*
 494 * Retrieve @GPtrArray for global property defined with options
 495 * other than "-global".  These are generally used for syntactic
 496 * sugar and legacy command line options.
 497 */
 498void object_register_sugar_prop(const char *driver, const char *prop,
 499                                const char *value, bool optional)
 500{
 501    GlobalProperty *g;
 502    if (!object_compat_props[2]) {
 503        object_compat_props[2] = g_ptr_array_new();
 504    }
 505    g = g_new0(GlobalProperty, 1);
 506    g->driver = g_strdup(driver);
 507    g->property = g_strdup(prop);
 508    g->value = g_strdup(value);
 509    g->optional = optional;
 510    g_ptr_array_add(object_compat_props[2], g);
 511}
 512
 513/*
 514 * Set machine's global property defaults to @compat_props.
 515 * May be called at most once.
 516 */
 517void object_set_machine_compat_props(GPtrArray *compat_props)
 518{
 519    assert(!object_compat_props[1]);
 520    object_compat_props[1] = compat_props;
 521}
 522
 523/*
 524 * Set accelerator's global property defaults to @compat_props.
 525 * May be called at most once.
 526 */
 527void object_set_accelerator_compat_props(GPtrArray *compat_props)
 528{
 529    assert(!object_compat_props[0]);
 530    object_compat_props[0] = compat_props;
 531}
 532
 533void object_apply_compat_props(Object *obj)
 534{
 535    int i;
 536
 537    for (i = 0; i < ARRAY_SIZE(object_compat_props); i++) {
 538        object_apply_global_props(obj, object_compat_props[i],
 539                                  i == 2 ? &error_fatal : &error_abort);
 540    }
 541}
 542
 543static void object_class_property_init_all(Object *obj)
 544{
 545    ObjectPropertyIterator iter;
 546    ObjectProperty *prop;
 547
 548    object_class_property_iter_init(&iter, object_get_class(obj));
 549    while ((prop = object_property_iter_next(&iter))) {
 550        if (prop->init) {
 551            prop->init(obj, prop);
 552        }
 553    }
 554}
 555
 556static void object_initialize_with_type(Object *obj, size_t size, TypeImpl *type)
 557{
 558    type_initialize(type);
 559
 560    g_assert(type->instance_size >= sizeof(Object));
 561    g_assert(type->abstract == false);
 562    g_assert(size >= type->instance_size);
 563
 564    memset(obj, 0, type->instance_size);
 565    obj->class = type->class;
 566    object_ref(obj);
 567    object_class_property_init_all(obj);
 568    obj->properties = g_hash_table_new_full(g_str_hash, g_str_equal,
 569                                            NULL, object_property_free);
 570    object_init_with_type(obj, type);
 571    object_post_init_with_type(obj, type);
 572}
 573
 574void object_initialize(void *data, size_t size, const char *typename)
 575{
 576    TypeImpl *type = type_get_or_load_by_name(typename, &error_fatal);
 577
 578    object_initialize_with_type(data, size, type);
 579}
 580
 581bool object_initialize_child_with_props(Object *parentobj,
 582                                        const char *propname,
 583                                        void *childobj, size_t size,
 584                                        const char *type,
 585                                        Error **errp, ...)
 586{
 587    va_list vargs;
 588    bool ok;
 589
 590    va_start(vargs, errp);
 591    ok = object_initialize_child_with_propsv(parentobj, propname,
 592                                             childobj, size, type, errp,
 593                                             vargs);
 594    va_end(vargs);
 595    return ok;
 596}
 597
 598bool object_initialize_child_with_propsv(Object *parentobj,
 599                                         const char *propname,
 600                                         void *childobj, size_t size,
 601                                         const char *type,
 602                                         Error **errp, va_list vargs)
 603{
 604    bool ok = false;
 605    Object *obj;
 606    UserCreatable *uc;
 607
 608    object_initialize(childobj, size, type);
 609    obj = OBJECT(childobj);
 610
 611    if (!object_set_propv(obj, errp, vargs)) {
 612        goto out;
 613    }
 614
 615    object_property_add_child(parentobj, propname, obj);
 616
 617    uc = (UserCreatable *)object_dynamic_cast(obj, TYPE_USER_CREATABLE);
 618    if (uc) {
 619        if (!user_creatable_complete(uc, errp)) {
 620            object_unparent(obj);
 621            goto out;
 622        }
 623    }
 624
 625    ok = true;
 626
 627out:
 628    /*
 629     * We want @obj's reference to be 1 on success, 0 on failure.
 630     * On success, it's 2: one taken by object_initialize(), and one
 631     * by object_property_add_child().
 632     * On failure in object_initialize() or earlier, it's 1.
 633     * On failure afterwards, it's also 1: object_unparent() releases
 634     * the reference taken by object_property_add_child().
 635     */
 636    object_unref(obj);
 637    return ok;
 638}
 639
 640void object_initialize_child_internal(Object *parent,
 641                                      const char *propname,
 642                                      void *child, size_t size,
 643                                      const char *type)
 644{
 645    object_initialize_child_with_props(parent, propname, child, size, type,
 646                                       &error_abort, NULL);
 647}
 648
 649static inline bool object_property_is_child(ObjectProperty *prop)
 650{
 651    return strstart(prop->type, "child<", NULL);
 652}
 653
 654static void object_property_del_all(Object *obj)
 655{
 656    g_autoptr(GHashTable) done = g_hash_table_new(NULL, NULL);
 657    ObjectProperty *prop;
 658    ObjectPropertyIterator iter;
 659    bool released;
 660
 661    do {
 662        released = false;
 663        object_property_iter_init(&iter, obj);
 664        while ((prop = object_property_iter_next(&iter)) != NULL) {
 665            if (g_hash_table_add(done, prop)) {
 666                if (prop->release) {
 667                    prop->release(obj, prop->name, prop->opaque);
 668                    released = true;
 669                    break;
 670                }
 671            }
 672        }
 673    } while (released);
 674
 675    g_hash_table_unref(obj->properties);
 676}
 677
 678static void object_property_del_child(Object *obj, Object *child)
 679{
 680    ObjectProperty *prop;
 681    GHashTableIter iter;
 682    gpointer key, value;
 683
 684    g_hash_table_iter_init(&iter, obj->properties);
 685    while (g_hash_table_iter_next(&iter, &key, &value)) {
 686        prop = value;
 687        if (object_property_is_child(prop) && prop->opaque == child) {
 688            if (prop->release) {
 689                prop->release(obj, prop->name, prop->opaque);
 690                prop->release = NULL;
 691            }
 692            break;
 693        }
 694    }
 695    g_hash_table_iter_init(&iter, obj->properties);
 696    while (g_hash_table_iter_next(&iter, &key, &value)) {
 697        prop = value;
 698        if (object_property_is_child(prop) && prop->opaque == child) {
 699            g_hash_table_iter_remove(&iter);
 700            break;
 701        }
 702    }
 703}
 704
 705void object_unparent(Object *obj)
 706{
 707    if (obj->parent) {
 708        object_property_del_child(obj->parent, obj);
 709    }
 710}
 711
 712static void object_deinit(Object *obj, TypeImpl *type)
 713{
 714    if (type->instance_finalize) {
 715        type->instance_finalize(obj);
 716    }
 717
 718    if (type_has_parent(type)) {
 719        object_deinit(obj, type_get_parent(type));
 720    }
 721}
 722
 723static void object_finalize(void *data)
 724{
 725    Object *obj = data;
 726    TypeImpl *ti = obj->class->type;
 727
 728    object_property_del_all(obj);
 729    object_deinit(obj, ti);
 730
 731    g_assert(obj->ref == 0);
 732    g_assert(obj->parent == NULL);
 733    if (obj->free) {
 734        obj->free(obj);
 735    }
 736}
 737
 738/* Find the minimum alignment guaranteed by the system malloc. */
 739#if __STDC_VERSION__ >= 201112L
 740typedef max_align_t qemu_max_align_t;
 741#else
 742typedef union {
 743    long l;
 744    void *p;
 745    double d;
 746    long double ld;
 747} qemu_max_align_t;
 748#endif
 749
 750static Object *object_new_with_type(Type type)
 751{
 752    Object *obj;
 753    size_t size, align;
 754    void (*obj_free)(void *);
 755
 756    g_assert(type != NULL);
 757    type_initialize(type);
 758
 759    size = type->instance_size;
 760    align = type->instance_align;
 761
 762    /*
 763     * Do not use qemu_memalign unless required.  Depending on the
 764     * implementation, extra alignment implies extra overhead.
 765     */
 766    if (likely(align <= __alignof__(qemu_max_align_t))) {
 767        obj = g_malloc(size);
 768        obj_free = g_free;
 769    } else {
 770        obj = qemu_memalign(align, size);
 771        obj_free = qemu_vfree;
 772    }
 773
 774    object_initialize_with_type(obj, size, type);
 775    obj->free = obj_free;
 776
 777    return obj;
 778}
 779
 780Object *object_new_with_class(ObjectClass *klass)
 781{
 782    return object_new_with_type(klass->type);
 783}
 784
 785Object *object_new(const char *typename)
 786{
 787    TypeImpl *ti = type_get_or_load_by_name(typename, &error_fatal);
 788
 789    return object_new_with_type(ti);
 790}
 791
 792
 793Object *object_new_with_props(const char *typename,
 794                              Object *parent,
 795                              const char *id,
 796                              Error **errp,
 797                              ...)
 798{
 799    va_list vargs;
 800    Object *obj;
 801
 802    va_start(vargs, errp);
 803    obj = object_new_with_propv(typename, parent, id, errp, vargs);
 804    va_end(vargs);
 805
 806    return obj;
 807}
 808
 809
 810Object *object_new_with_propv(const char *typename,
 811                              Object *parent,
 812                              const char *id,
 813                              Error **errp,
 814                              va_list vargs)
 815{
 816    Object *obj;
 817    ObjectClass *klass;
 818    UserCreatable *uc;
 819
 820    klass = object_class_by_name(typename);
 821    if (!klass) {
 822        error_setg(errp, "invalid object type: %s", typename);
 823        return NULL;
 824    }
 825
 826    if (object_class_is_abstract(klass)) {
 827        error_setg(errp, "object type '%s' is abstract", typename);
 828        return NULL;
 829    }
 830    obj = object_new_with_type(klass->type);
 831
 832    if (!object_set_propv(obj, errp, vargs)) {
 833        goto error;
 834    }
 835
 836    if (id != NULL) {
 837        object_property_add_child(parent, id, obj);
 838    }
 839
 840    uc = (UserCreatable *)object_dynamic_cast(obj, TYPE_USER_CREATABLE);
 841    if (uc) {
 842        if (!user_creatable_complete(uc, errp)) {
 843            if (id != NULL) {
 844                object_unparent(obj);
 845            }
 846            goto error;
 847        }
 848    }
 849
 850    object_unref(obj);
 851    return obj;
 852
 853 error:
 854    object_unref(obj);
 855    return NULL;
 856}
 857
 858
 859bool object_set_props(Object *obj,
 860                     Error **errp,
 861                     ...)
 862{
 863    va_list vargs;
 864    bool ret;
 865
 866    va_start(vargs, errp);
 867    ret = object_set_propv(obj, errp, vargs);
 868    va_end(vargs);
 869
 870    return ret;
 871}
 872
 873
 874bool object_set_propv(Object *obj,
 875                     Error **errp,
 876                     va_list vargs)
 877{
 878    const char *propname;
 879
 880    propname = va_arg(vargs, char *);
 881    while (propname != NULL) {
 882        const char *value = va_arg(vargs, char *);
 883
 884        g_assert(value != NULL);
 885        if (!object_property_parse(obj, propname, value, errp)) {
 886            return false;
 887        }
 888        propname = va_arg(vargs, char *);
 889    }
 890
 891    return true;
 892}
 893
 894
 895Object *object_dynamic_cast(Object *obj, const char *typename)
 896{
 897    if (obj && object_class_dynamic_cast(object_get_class(obj), typename)) {
 898        return obj;
 899    }
 900
 901    return NULL;
 902}
 903
 904Object *object_dynamic_cast_assert(Object *obj, const char *typename,
 905                                   const char *file, int line, const char *func)
 906{
 907    trace_object_dynamic_cast_assert(obj ? obj->class->type->name : "(null)",
 908                                     typename, file, line, func);
 909
 910#ifdef CONFIG_QOM_CAST_DEBUG
 911    int i;
 912    Object *inst;
 913
 914    for (i = 0; obj && i < OBJECT_CLASS_CAST_CACHE; i++) {
 915        if (qatomic_read(&obj->class->object_cast_cache[i]) == typename) {
 916            goto out;
 917        }
 918    }
 919
 920    inst = object_dynamic_cast(obj, typename);
 921
 922    if (!inst && obj) {
 923        fprintf(stderr, "%s:%d:%s: Object %p is not an instance of type %s\n",
 924                file, line, func, obj, typename);
 925        abort();
 926    }
 927
 928    assert(obj == inst);
 929
 930    if (obj && obj == inst) {
 931        for (i = 1; i < OBJECT_CLASS_CAST_CACHE; i++) {
 932            qatomic_set(&obj->class->object_cast_cache[i - 1],
 933                       qatomic_read(&obj->class->object_cast_cache[i]));
 934        }
 935        qatomic_set(&obj->class->object_cast_cache[i - 1], typename);
 936    }
 937
 938out:
 939#endif
 940    return obj;
 941}
 942
 943ObjectClass *object_class_dynamic_cast(ObjectClass *class,
 944                                       const char *typename)
 945{
 946    ObjectClass *ret = NULL;
 947    TypeImpl *target_type;
 948    TypeImpl *type;
 949
 950    if (!class) {
 951        return NULL;
 952    }
 953
 954    /* A simple fast path that can trigger a lot for leaf classes.  */
 955    type = class->type;
 956    if (type->name == typename) {
 957        return class;
 958    }
 959
 960    target_type = type_get_by_name_noload(typename);
 961    if (!target_type) {
 962        /* target class type unknown, so fail the cast */
 963        return NULL;
 964    }
 965
 966    if (type->class->interfaces &&
 967            type_is_ancestor(target_type, type_interface)) {
 968        int found = 0;
 969        GSList *i;
 970
 971        for (i = class->interfaces; i; i = i->next) {
 972            ObjectClass *target_class = i->data;
 973
 974            if (type_is_ancestor(target_class->type, target_type)) {
 975                ret = target_class;
 976                found++;
 977            }
 978         }
 979
 980        /* The match was ambiguous, don't allow a cast */
 981        if (found > 1) {
 982            ret = NULL;
 983        }
 984    } else if (type_is_ancestor(type, target_type)) {
 985        ret = class;
 986    }
 987
 988    return ret;
 989}
 990
 991ObjectClass *object_class_dynamic_cast_assert(ObjectClass *class,
 992                                              const char *typename,
 993                                              const char *file, int line,
 994                                              const char *func)
 995{
 996    ObjectClass *ret;
 997
 998    trace_object_class_dynamic_cast_assert(class ? class->type->name : "(null)",
 999                                           typename, file, line, func);
1000
1001#ifdef CONFIG_QOM_CAST_DEBUG
1002    int i;
1003
1004    for (i = 0; class && i < OBJECT_CLASS_CAST_CACHE; i++) {
1005        if (qatomic_read(&class->class_cast_cache[i]) == typename) {
1006            ret = class;
1007            goto out;
1008        }
1009    }
1010#else
1011    if (!class || !class->interfaces) {
1012        return class;
1013    }
1014#endif
1015
1016    ret = object_class_dynamic_cast(class, typename);
1017    if (!ret && class) {
1018        fprintf(stderr, "%s:%d:%s: Object %p is not an instance of type %s\n",
1019                file, line, func, class, typename);
1020        abort();
1021    }
1022
1023#ifdef CONFIG_QOM_CAST_DEBUG
1024    if (class && ret == class) {
1025        for (i = 1; i < OBJECT_CLASS_CAST_CACHE; i++) {
1026            qatomic_set(&class->class_cast_cache[i - 1],
1027                       qatomic_read(&class->class_cast_cache[i]));
1028        }
1029        qatomic_set(&class->class_cast_cache[i - 1], typename);
1030    }
1031out:
1032#endif
1033    return ret;
1034}
1035
1036const char *object_get_typename(const Object *obj)
1037{
1038    return obj->class->type->name;
1039}
1040
1041ObjectClass *object_get_class(Object *obj)
1042{
1043    return obj->class;
1044}
1045
1046bool object_class_is_abstract(ObjectClass *klass)
1047{
1048    return klass->type->abstract;
1049}
1050
1051const char *object_class_get_name(ObjectClass *klass)
1052{
1053    return klass->type->name;
1054}
1055
1056ObjectClass *object_class_by_name(const char *typename)
1057{
1058    TypeImpl *type = type_get_by_name_noload(typename);
1059
1060    if (!type) {
1061        return NULL;
1062    }
1063
1064    type_initialize(type);
1065
1066    return type->class;
1067}
1068
1069ObjectClass *module_object_class_by_name(const char *typename)
1070{
1071    TypeImpl *type = type_get_or_load_by_name(typename, NULL);
1072
1073    if (!type) {
1074        return NULL;
1075    }
1076
1077    type_initialize(type);
1078
1079    return type->class;
1080}
1081
1082ObjectClass *object_class_get_parent(ObjectClass *class)
1083{
1084    TypeImpl *type = type_get_parent(class->type);
1085
1086    if (!type) {
1087        return NULL;
1088    }
1089
1090    type_initialize(type);
1091
1092    return type->class;
1093}
1094
1095typedef struct OCFData
1096{
1097    void (*fn)(ObjectClass *klass, void *opaque);
1098    const char *implements_type;
1099    bool include_abstract;
1100    void *opaque;
1101} OCFData;
1102
1103static void object_class_foreach_tramp(gpointer key, gpointer value,
1104                                       gpointer opaque)
1105{
1106    OCFData *data = opaque;
1107    TypeImpl *type = value;
1108    ObjectClass *k;
1109
1110    type_initialize(type);
1111    k = type->class;
1112
1113    if (!data->include_abstract && type->abstract) {
1114        return;
1115    }
1116
1117    if (data->implements_type && 
1118        !object_class_dynamic_cast(k, data->implements_type)) {
1119        return;
1120    }
1121
1122    data->fn(k, data->opaque);
1123}
1124
1125void object_class_foreach(void (*fn)(ObjectClass *klass, void *opaque),
1126                          const char *implements_type, bool include_abstract,
1127                          void *opaque)
1128{
1129    OCFData data = { fn, implements_type, include_abstract, opaque };
1130
1131    enumerating_types = true;
1132    g_hash_table_foreach(type_table_get(), object_class_foreach_tramp, &data);
1133    enumerating_types = false;
1134}
1135
1136static int do_object_child_foreach(Object *obj,
1137                                   int (*fn)(Object *child, void *opaque),
1138                                   void *opaque, bool recurse)
1139{
1140    GHashTableIter iter;
1141    ObjectProperty *prop;
1142    int ret = 0;
1143
1144    g_hash_table_iter_init(&iter, obj->properties);
1145    while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&prop)) {
1146        if (object_property_is_child(prop)) {
1147            Object *child = prop->opaque;
1148
1149            ret = fn(child, opaque);
1150            if (ret != 0) {
1151                break;
1152            }
1153            if (recurse) {
1154                ret = do_object_child_foreach(child, fn, opaque, true);
1155                if (ret != 0) {
1156                    break;
1157                }
1158            }
1159        }
1160    }
1161    return ret;
1162}
1163
1164int object_child_foreach(Object *obj, int (*fn)(Object *child, void *opaque),
1165                         void *opaque)
1166{
1167    return do_object_child_foreach(obj, fn, opaque, false);
1168}
1169
1170int object_child_foreach_recursive(Object *obj,
1171                                   int (*fn)(Object *child, void *opaque),
1172                                   void *opaque)
1173{
1174    return do_object_child_foreach(obj, fn, opaque, true);
1175}
1176
1177static void object_class_get_list_tramp(ObjectClass *klass, void *opaque)
1178{
1179    GSList **list = opaque;
1180
1181    *list = g_slist_prepend(*list, klass);
1182}
1183
1184GSList *object_class_get_list(const char *implements_type,
1185                              bool include_abstract)
1186{
1187    GSList *list = NULL;
1188
1189    object_class_foreach(object_class_get_list_tramp,
1190                         implements_type, include_abstract, &list);
1191    return list;
1192}
1193
1194static gint object_class_cmp(gconstpointer a, gconstpointer b, gpointer d)
1195{
1196    return strcasecmp(object_class_get_name((ObjectClass *)a),
1197                      object_class_get_name((ObjectClass *)b));
1198}
1199
1200GSList *object_class_get_list_sorted(const char *implements_type,
1201                                     bool include_abstract)
1202{
1203    return g_slist_sort_with_data(
1204        object_class_get_list(implements_type, include_abstract),
1205        object_class_cmp, NULL);
1206}
1207
1208Object *object_ref(void *objptr)
1209{
1210    Object *obj = OBJECT(objptr);
1211    uint32_t ref;
1212
1213    if (!obj) {
1214        return NULL;
1215    }
1216    ref = qatomic_fetch_inc(&obj->ref);
1217    /* Assert waaay before the integer overflows */
1218    g_assert(ref < INT_MAX);
1219    return obj;
1220}
1221
1222void object_unref(void *objptr)
1223{
1224    Object *obj = OBJECT(objptr);
1225    if (!obj) {
1226        return;
1227    }
1228    g_assert(obj->ref > 0);
1229
1230    /* parent always holds a reference to its children */
1231    if (qatomic_fetch_dec(&obj->ref) == 1) {
1232        object_finalize(obj);
1233    }
1234}
1235
1236ObjectProperty *
1237object_property_try_add(Object *obj, const char *name, const char *type,
1238                        ObjectPropertyAccessor *get,
1239                        ObjectPropertyAccessor *set,
1240                        ObjectPropertyRelease *release,
1241                        void *opaque, Error **errp)
1242{
1243    ObjectProperty *prop;
1244    size_t name_len = strlen(name);
1245
1246    if (name_len >= 3 && !memcmp(name + name_len - 3, "[*]", 4)) {
1247        int i;
1248        ObjectProperty *ret = NULL;
1249        char *name_no_array = g_strdup(name);
1250
1251        name_no_array[name_len - 3] = '\0';
1252        for (i = 0; i < INT16_MAX; ++i) {
1253            char *full_name = g_strdup_printf("%s[%d]", name_no_array, i);
1254
1255            ret = object_property_try_add(obj, full_name, type, get, set,
1256                                          release, opaque, NULL);
1257            g_free(full_name);
1258            if (ret) {
1259                break;
1260            }
1261        }
1262        g_free(name_no_array);
1263        assert(ret);
1264        return ret;
1265    }
1266
1267    if (object_property_find(obj, name) != NULL) {
1268        error_setg(errp, "attempt to add duplicate property '%s' to object (type '%s')",
1269                   name, object_get_typename(obj));
1270        return NULL;
1271    }
1272
1273    prop = g_malloc0(sizeof(*prop));
1274
1275    prop->name = g_strdup(name);
1276    prop->type = g_strdup(type);
1277
1278    prop->get = get;
1279    prop->set = set;
1280    prop->release = release;
1281    prop->opaque = opaque;
1282
1283    g_hash_table_insert(obj->properties, prop->name, prop);
1284    return prop;
1285}
1286
1287ObjectProperty *
1288object_property_add(Object *obj, const char *name, const char *type,
1289                    ObjectPropertyAccessor *get,
1290                    ObjectPropertyAccessor *set,
1291                    ObjectPropertyRelease *release,
1292                    void *opaque)
1293{
1294    return object_property_try_add(obj, name, type, get, set, release,
1295                                   opaque, &error_abort);
1296}
1297
1298ObjectProperty *
1299object_class_property_add(ObjectClass *klass,
1300                          const char *name,
1301                          const char *type,
1302                          ObjectPropertyAccessor *get,
1303                          ObjectPropertyAccessor *set,
1304                          ObjectPropertyRelease *release,
1305                          void *opaque)
1306{
1307    ObjectProperty *prop;
1308
1309    assert(!object_class_property_find(klass, name));
1310
1311    prop = g_malloc0(sizeof(*prop));
1312
1313    prop->name = g_strdup(name);
1314    prop->type = g_strdup(type);
1315
1316    prop->get = get;
1317    prop->set = set;
1318    prop->release = release;
1319    prop->opaque = opaque;
1320
1321    g_hash_table_insert(klass->properties, prop->name, prop);
1322
1323    return prop;
1324}
1325
1326ObjectProperty *object_property_find(Object *obj, const char *name)
1327{
1328    ObjectProperty *prop;
1329    ObjectClass *klass = object_get_class(obj);
1330
1331    prop = object_class_property_find(klass, name);
1332    if (prop) {
1333        return prop;
1334    }
1335
1336    return g_hash_table_lookup(obj->properties, name);
1337}
1338
1339ObjectProperty *object_property_find_err(Object *obj, const char *name,
1340                                         Error **errp)
1341{
1342    ObjectProperty *prop = object_property_find(obj, name);
1343    if (!prop) {
1344        error_setg(errp, "Property '%s.%s' not found",
1345                   object_get_typename(obj), name);
1346    }
1347    return prop;
1348}
1349
1350void object_property_iter_init(ObjectPropertyIterator *iter,
1351                               Object *obj)
1352{
1353    g_hash_table_iter_init(&iter->iter, obj->properties);
1354    iter->nextclass = object_get_class(obj);
1355}
1356
1357ObjectProperty *object_property_iter_next(ObjectPropertyIterator *iter)
1358{
1359    gpointer key, val;
1360    while (!g_hash_table_iter_next(&iter->iter, &key, &val)) {
1361        if (!iter->nextclass) {
1362            return NULL;
1363        }
1364        g_hash_table_iter_init(&iter->iter, iter->nextclass->properties);
1365        iter->nextclass = object_class_get_parent(iter->nextclass);
1366    }
1367    return val;
1368}
1369
1370void object_class_property_iter_init(ObjectPropertyIterator *iter,
1371                                     ObjectClass *klass)
1372{
1373    g_hash_table_iter_init(&iter->iter, klass->properties);
1374    iter->nextclass = object_class_get_parent(klass);
1375}
1376
1377ObjectProperty *object_class_property_find(ObjectClass *klass, const char *name)
1378{
1379    ObjectClass *parent_klass;
1380
1381    parent_klass = object_class_get_parent(klass);
1382    if (parent_klass) {
1383        ObjectProperty *prop =
1384            object_class_property_find(parent_klass, name);
1385        if (prop) {
1386            return prop;
1387        }
1388    }
1389
1390    return g_hash_table_lookup(klass->properties, name);
1391}
1392
1393ObjectProperty *object_class_property_find_err(ObjectClass *klass,
1394                                               const char *name,
1395                                               Error **errp)
1396{
1397    ObjectProperty *prop = object_class_property_find(klass, name);
1398    if (!prop) {
1399        error_setg(errp, "Property '.%s' not found", name);
1400    }
1401    return prop;
1402}
1403
1404
1405void object_property_del(Object *obj, const char *name)
1406{
1407    ObjectProperty *prop = g_hash_table_lookup(obj->properties, name);
1408
1409    if (prop->release) {
1410        prop->release(obj, name, prop->opaque);
1411    }
1412    g_hash_table_remove(obj->properties, name);
1413}
1414
1415bool object_property_get(Object *obj, const char *name, Visitor *v,
1416                         Error **errp)
1417{
1418    Error *err = NULL;
1419    ObjectProperty *prop = object_property_find_err(obj, name, errp);
1420
1421    if (prop == NULL) {
1422        return false;
1423    }
1424
1425    if (!prop->get) {
1426        error_setg(errp, "Property '%s.%s' is not readable",
1427                   object_get_typename(obj), name);
1428        return false;
1429    }
1430    prop->get(obj, v, name, prop->opaque, &err);
1431    error_propagate(errp, err);
1432    return !err;
1433}
1434
1435bool object_property_set(Object *obj, const char *name, Visitor *v,
1436                         Error **errp)
1437{
1438    ERRP_GUARD();
1439    ObjectProperty *prop = object_property_find_err(obj, name, errp);
1440
1441    if (prop == NULL) {
1442        return false;
1443    }
1444
1445    if (!prop->set) {
1446        error_setg(errp, "Property '%s.%s' is not writable",
1447                   object_get_typename(obj), name);
1448        return false;
1449    }
1450    prop->set(obj, v, name, prop->opaque, errp);
1451    return !*errp;
1452}
1453
1454bool object_property_set_str(Object *obj, const char *name,
1455                             const char *value, Error **errp)
1456{
1457    QString *qstr = qstring_from_str(value);
1458    bool ok = object_property_set_qobject(obj, name, QOBJECT(qstr), errp);
1459
1460    qobject_unref(qstr);
1461    return ok;
1462}
1463
1464char *object_property_get_str(Object *obj, const char *name,
1465                              Error **errp)
1466{
1467    QObject *ret = object_property_get_qobject(obj, name, errp);
1468    QString *qstring;
1469    char *retval;
1470
1471    if (!ret) {
1472        return NULL;
1473    }
1474    qstring = qobject_to(QString, ret);
1475    if (!qstring) {
1476        error_setg(errp, "Invalid parameter type for '%s', expected: string",
1477                   name);
1478        retval = NULL;
1479    } else {
1480        retval = g_strdup(qstring_get_str(qstring));
1481    }
1482
1483    qobject_unref(ret);
1484    return retval;
1485}
1486
1487bool object_property_set_link(Object *obj, const char *name,
1488                              Object *value, Error **errp)
1489{
1490    g_autofree char *path = NULL;
1491
1492    if (value) {
1493        path = object_get_canonical_path(value);
1494    }
1495    return object_property_set_str(obj, name, path ?: "", errp);
1496}
1497
1498Object *object_property_get_link(Object *obj, const char *name,
1499                                 Error **errp)
1500{
1501    char *str = object_property_get_str(obj, name, errp);
1502    Object *target = NULL;
1503
1504    if (str && *str) {
1505        target = object_resolve_path(str, NULL);
1506        if (!target) {
1507            error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
1508                      "Device '%s' not found", str);
1509        }
1510    }
1511
1512    g_free(str);
1513    return target;
1514}
1515
1516bool object_property_set_bool(Object *obj, const char *name,
1517                              bool value, Error **errp)
1518{
1519    QBool *qbool = qbool_from_bool(value);
1520    bool ok = object_property_set_qobject(obj, name, QOBJECT(qbool), errp);
1521
1522    qobject_unref(qbool);
1523    return ok;
1524}
1525
1526bool object_property_get_bool(Object *obj, const char *name,
1527                              Error **errp)
1528{
1529    QObject *ret = object_property_get_qobject(obj, name, errp);
1530    QBool *qbool;
1531    bool retval;
1532
1533    if (!ret) {
1534        return false;
1535    }
1536    qbool = qobject_to(QBool, ret);
1537    if (!qbool) {
1538        error_setg(errp, "Invalid parameter type for '%s', expected: boolean",
1539                   name);
1540        retval = false;
1541    } else {
1542        retval = qbool_get_bool(qbool);
1543    }
1544
1545    qobject_unref(ret);
1546    return retval;
1547}
1548
1549bool object_property_set_int(Object *obj, const char *name,
1550                             int64_t value, Error **errp)
1551{
1552    QNum *qnum = qnum_from_int(value);
1553    bool ok = object_property_set_qobject(obj, name, QOBJECT(qnum), errp);
1554
1555    qobject_unref(qnum);
1556    return ok;
1557}
1558
1559int64_t object_property_get_int(Object *obj, const char *name,
1560                                Error **errp)
1561{
1562    QObject *ret = object_property_get_qobject(obj, name, errp);
1563    QNum *qnum;
1564    int64_t retval;
1565
1566    if (!ret) {
1567        return -1;
1568    }
1569
1570    qnum = qobject_to(QNum, ret);
1571    if (!qnum || !qnum_get_try_int(qnum, &retval)) {
1572        error_setg(errp, "Invalid parameter type for '%s', expected: int",
1573                   name);
1574        retval = -1;
1575    }
1576
1577    qobject_unref(ret);
1578    return retval;
1579}
1580
1581static void object_property_init_defval(Object *obj, ObjectProperty *prop)
1582{
1583    Visitor *v = qobject_input_visitor_new(prop->defval);
1584
1585    assert(prop->set != NULL);
1586    prop->set(obj, v, prop->name, prop->opaque, &error_abort);
1587
1588    visit_free(v);
1589}
1590
1591static void object_property_set_default(ObjectProperty *prop, QObject *defval)
1592{
1593    assert(!prop->defval);
1594    assert(!prop->init);
1595
1596    prop->defval = defval;
1597    prop->init = object_property_init_defval;
1598}
1599
1600void object_property_set_default_bool(ObjectProperty *prop, bool value)
1601{
1602    object_property_set_default(prop, QOBJECT(qbool_from_bool(value)));
1603}
1604
1605void object_property_set_default_str(ObjectProperty *prop, const char *value)
1606{
1607    object_property_set_default(prop, QOBJECT(qstring_from_str(value)));
1608}
1609
1610void object_property_set_default_list(ObjectProperty *prop)
1611{
1612    object_property_set_default(prop, QOBJECT(qlist_new()));
1613}
1614
1615void object_property_set_default_int(ObjectProperty *prop, int64_t value)
1616{
1617    object_property_set_default(prop, QOBJECT(qnum_from_int(value)));
1618}
1619
1620void object_property_set_default_uint(ObjectProperty *prop, uint64_t value)
1621{
1622    object_property_set_default(prop, QOBJECT(qnum_from_uint(value)));
1623}
1624
1625bool object_property_set_uint(Object *obj, const char *name,
1626                              uint64_t value, Error **errp)
1627{
1628    QNum *qnum = qnum_from_uint(value);
1629    bool ok = object_property_set_qobject(obj, name, QOBJECT(qnum), errp);
1630
1631    qobject_unref(qnum);
1632    return ok;
1633}
1634
1635uint64_t object_property_get_uint(Object *obj, const char *name,
1636                                  Error **errp)
1637{
1638    QObject *ret = object_property_get_qobject(obj, name, errp);
1639    QNum *qnum;
1640    uint64_t retval;
1641
1642    if (!ret) {
1643        return 0;
1644    }
1645    qnum = qobject_to(QNum, ret);
1646    if (!qnum || !qnum_get_try_uint(qnum, &retval)) {
1647        error_setg(errp, "Invalid parameter type for '%s', expected: uint",
1648                   name);
1649        retval = 0;
1650    }
1651
1652    qobject_unref(ret);
1653    return retval;
1654}
1655
1656typedef struct EnumProperty {
1657    const QEnumLookup *lookup;
1658    int (*get)(Object *, Error **);
1659    void (*set)(Object *, int, Error **);
1660} EnumProperty;
1661
1662int object_property_get_enum(Object *obj, const char *name,
1663                             const char *typename, Error **errp)
1664{
1665    char *str;
1666    int ret;
1667    ObjectProperty *prop = object_property_find_err(obj, name, errp);
1668    EnumProperty *enumprop;
1669
1670    if (prop == NULL) {
1671        return -1;
1672    }
1673
1674    if (!g_str_equal(prop->type, typename)) {
1675        error_setg(errp, "Property %s on %s is not '%s' enum type",
1676                   name, object_class_get_name(
1677                       object_get_class(obj)), typename);
1678        return -1;
1679    }
1680
1681    enumprop = prop->opaque;
1682
1683    str = object_property_get_str(obj, name, errp);
1684    if (!str) {
1685        return -1;
1686    }
1687
1688    ret = qapi_enum_parse(enumprop->lookup, str, -1, errp);
1689    g_free(str);
1690
1691    return ret;
1692}
1693
1694bool object_property_parse(Object *obj, const char *name,
1695                           const char *string, Error **errp)
1696{
1697    Visitor *v = string_input_visitor_new(string);
1698    bool ok = object_property_set(obj, name, v, errp);
1699
1700    visit_free(v);
1701    return ok;
1702}
1703
1704char *object_property_print(Object *obj, const char *name, bool human,
1705                            Error **errp)
1706{
1707    Visitor *v;
1708    char *string = NULL;
1709
1710    v = string_output_visitor_new(human, &string);
1711    if (!object_property_get(obj, name, v, errp)) {
1712        goto out;
1713    }
1714
1715    visit_complete(v, &string);
1716
1717out:
1718    visit_free(v);
1719    return string;
1720}
1721
1722const char *object_property_get_type(Object *obj, const char *name, Error **errp)
1723{
1724    ObjectProperty *prop = object_property_find_err(obj, name, errp);
1725    if (prop == NULL) {
1726        return NULL;
1727    }
1728
1729    return prop->type;
1730}
1731
1732static const char *const root_containers[] = {
1733    "chardevs",
1734    "objects",
1735    "backend"
1736};
1737
1738static Object *object_root_initialize(void)
1739{
1740    Object *root = object_new(TYPE_CONTAINER);
1741    int i;
1742
1743    /*
1744     * Create all QEMU system containers.  "machine" and its sub-containers
1745     * are only created when machine initializes (qemu_create_machine()).
1746     */
1747    for (i = 0; i < ARRAY_SIZE(root_containers); i++) {
1748        object_property_add_new_container(root, root_containers[i]);
1749    }
1750
1751    return root;
1752}
1753
1754Object *object_get_container(const char *name)
1755{
1756    Object *container;
1757
1758    container = object_resolve_path_component(object_get_root(), name);
1759    assert(object_dynamic_cast(container, TYPE_CONTAINER));
1760
1761    return container;
1762}
1763
1764Object *object_get_root(void)
1765{
1766    static Object *root;
1767
1768    if (!root) {
1769        root = object_root_initialize();
1770    }
1771
1772    return root;
1773}
1774
1775Object *object_get_objects_root(void)
1776{
1777    return object_get_container("objects");
1778}
1779
1780Object *object_get_internal_root(void)
1781{
1782    static Object *internal_root;
1783
1784    if (!internal_root) {
1785        internal_root = object_new(TYPE_CONTAINER);
1786    }
1787
1788    return internal_root;
1789}
1790
1791static void object_get_child_property(Object *obj, Visitor *v,
1792                                      const char *name, void *opaque,
1793                                      Error **errp)
1794{
1795    Object *child = opaque;
1796    char *path;
1797
1798    path = object_get_canonical_path(child);
1799    visit_type_str(v, name, &path, errp);
1800    g_free(path);
1801}
1802
1803static Object *object_resolve_child_property(Object *parent, void *opaque,
1804                                             const char *part)
1805{
1806    return opaque;
1807}
1808
1809static void object_finalize_child_property(Object *obj, const char *name,
1810                                           void *opaque)
1811{
1812    Object *child = opaque;
1813
1814    if (child->class->unparent) {
1815        (child->class->unparent)(child);
1816    }
1817    child->parent = NULL;
1818    object_unref(child);
1819}
1820
1821ObjectProperty *
1822object_property_try_add_child(Object *obj, const char *name,
1823                              Object *child, Error **errp)
1824{
1825    g_autofree char *type = NULL;
1826    ObjectProperty *op;
1827
1828    assert(!child->parent);
1829
1830    type = g_strdup_printf("child<%s>", object_get_typename(child));
1831
1832    op = object_property_try_add(obj, name, type, object_get_child_property,
1833                                 NULL, object_finalize_child_property,
1834                                 child, errp);
1835    if (!op) {
1836        return NULL;
1837    }
1838    op->resolve = object_resolve_child_property;
1839    object_ref(child);
1840    child->parent = obj;
1841    return op;
1842}
1843
1844ObjectProperty *
1845object_property_add_child(Object *obj, const char *name,
1846                          Object *child)
1847{
1848    return object_property_try_add_child(obj, name, child, &error_abort);
1849}
1850
1851void object_property_allow_set_link(const Object *obj, const char *name,
1852                                    Object *val, Error **errp)
1853{
1854    /* Allow the link to be set, always */
1855}
1856
1857typedef struct {
1858    union {
1859        Object **targetp;
1860        Object *target; /* if OBJ_PROP_LINK_DIRECT, when holding the pointer  */
1861        ptrdiff_t offset; /* if OBJ_PROP_LINK_CLASS */
1862    };
1863    void (*check)(const Object *, const char *, Object *, Error **);
1864    ObjectPropertyLinkFlags flags;
1865} LinkProperty;
1866
1867static Object **
1868object_link_get_targetp(Object *obj, LinkProperty *lprop)
1869{
1870    if (lprop->flags & OBJ_PROP_LINK_DIRECT) {
1871        return &lprop->target;
1872    } else if (lprop->flags & OBJ_PROP_LINK_CLASS) {
1873        return (void *)obj + lprop->offset;
1874    } else {
1875        return lprop->targetp;
1876    }
1877}
1878
1879static void object_get_link_property(Object *obj, Visitor *v,
1880                                     const char *name, void *opaque,
1881                                     Error **errp)
1882{
1883    LinkProperty *lprop = opaque;
1884    Object **targetp = object_link_get_targetp(obj, lprop);
1885    char *path;
1886
1887    if (*targetp) {
1888        path = object_get_canonical_path(*targetp);
1889        visit_type_str(v, name, &path, errp);
1890        g_free(path);
1891    } else {
1892        path = (char *)"";
1893        visit_type_str(v, name, &path, errp);
1894    }
1895}
1896
1897/*
1898 * object_resolve_link:
1899 *
1900 * Lookup an object and ensure its type matches the link property type.  This
1901 * is similar to object_resolve_path() except type verification against the
1902 * link property is performed.
1903 *
1904 * Returns: The matched object or NULL on path lookup failures.
1905 */
1906static Object *object_resolve_link(Object *obj, const char *name,
1907                                   const char *path, Error **errp)
1908{
1909    const char *type;
1910    char *target_type;
1911    bool ambiguous = false;
1912    Object *target;
1913
1914    /* Go from link<FOO> to FOO.  */
1915    type = object_property_get_type(obj, name, NULL);
1916    target_type = g_strndup(&type[5], strlen(type) - 6);
1917    target = object_resolve_path_type(path, target_type, &ambiguous);
1918
1919    if (ambiguous) {
1920        error_setg(errp, "Path '%s' does not uniquely identify an object",
1921                   path);
1922    } else if (!target) {
1923        target = object_resolve_path(path, &ambiguous);
1924        if (target || ambiguous) {
1925            error_setg(errp, "Invalid parameter type for '%s', expected: %s",
1926                             name, target_type);
1927        } else {
1928            error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
1929                      "Device '%s' not found", path);
1930        }
1931        target = NULL;
1932    }
1933    g_free(target_type);
1934
1935    return target;
1936}
1937
1938static void object_set_link_property(Object *obj, Visitor *v,
1939                                     const char *name, void *opaque,
1940                                     Error **errp)
1941{
1942    Error *local_err = NULL;
1943    LinkProperty *prop = opaque;
1944    Object **targetp = object_link_get_targetp(obj, prop);
1945    Object *old_target = *targetp;
1946    Object *new_target;
1947    char *path = NULL;
1948
1949    if (!visit_type_str(v, name, &path, errp)) {
1950        return;
1951    }
1952
1953    if (*path) {
1954        new_target = object_resolve_link(obj, name, path, errp);
1955        if (!new_target) {
1956            g_free(path);
1957            return;
1958        }
1959    } else {
1960        new_target = NULL;
1961    }
1962
1963    g_free(path);
1964
1965    prop->check(obj, name, new_target, &local_err);
1966    if (local_err) {
1967        error_propagate(errp, local_err);
1968        return;
1969    }
1970
1971    *targetp = new_target;
1972    if (prop->flags & OBJ_PROP_LINK_STRONG) {
1973        object_ref(new_target);
1974        object_unref(old_target);
1975    }
1976}
1977
1978static Object *object_resolve_link_property(Object *parent, void *opaque,
1979                                            const char *part)
1980{
1981    LinkProperty *lprop = opaque;
1982
1983    return *object_link_get_targetp(parent, lprop);
1984}
1985
1986static void object_release_link_property(Object *obj, const char *name,
1987                                         void *opaque)
1988{
1989    LinkProperty *prop = opaque;
1990    Object **targetp = object_link_get_targetp(obj, prop);
1991
1992    if ((prop->flags & OBJ_PROP_LINK_STRONG) && *targetp) {
1993        object_unref(*targetp);
1994    }
1995    if (!(prop->flags & OBJ_PROP_LINK_CLASS)) {
1996        g_free(prop);
1997    }
1998}
1999
2000static ObjectProperty *
2001object_add_link_prop(Object *obj, const char *name,
2002                     const char *type, void *ptr,
2003                     void (*check)(const Object *, const char *,
2004                                   Object *, Error **),
2005                     ObjectPropertyLinkFlags flags)
2006{
2007    LinkProperty *prop = g_malloc(sizeof(*prop));
2008    g_autofree char *full_type = NULL;
2009    ObjectProperty *op;
2010
2011    if (flags & OBJ_PROP_LINK_DIRECT) {
2012        prop->target = ptr;
2013    } else {
2014        prop->targetp = ptr;
2015    }
2016    prop->check = check;
2017    prop->flags = flags;
2018
2019    full_type = g_strdup_printf("link<%s>", type);
2020
2021    op = object_property_add(obj, name, full_type,
2022                             object_get_link_property,
2023                             check ? object_set_link_property : NULL,
2024                             object_release_link_property,
2025                             prop);
2026    op->resolve = object_resolve_link_property;
2027    return op;
2028}
2029
2030ObjectProperty *
2031object_property_add_link(Object *obj, const char *name,
2032                         const char *type, Object **targetp,
2033                         void (*check)(const Object *, const char *,
2034                                       Object *, Error **),
2035                         ObjectPropertyLinkFlags flags)
2036{
2037    return object_add_link_prop(obj, name, type, targetp, check, flags);
2038}
2039
2040ObjectProperty *
2041object_class_property_add_link(ObjectClass *oc,
2042    const char *name,
2043    const char *type, ptrdiff_t offset,
2044    void (*check)(const Object *obj, const char *name,
2045                  Object *val, Error **errp),
2046    ObjectPropertyLinkFlags flags)
2047{
2048    LinkProperty *prop = g_new0(LinkProperty, 1);
2049    char *full_type;
2050    ObjectProperty *op;
2051
2052    prop->offset = offset;
2053    prop->check = check;
2054    prop->flags = flags | OBJ_PROP_LINK_CLASS;
2055
2056    full_type = g_strdup_printf("link<%s>", type);
2057
2058    op = object_class_property_add(oc, name, full_type,
2059                                   object_get_link_property,
2060                                   check ? object_set_link_property : NULL,
2061                                   object_release_link_property,
2062                                   prop);
2063
2064    op->resolve = object_resolve_link_property;
2065
2066    g_free(full_type);
2067    return op;
2068}
2069
2070ObjectProperty *
2071object_property_add_const_link(Object *obj, const char *name,
2072                               Object *target)
2073{
2074    return object_add_link_prop(obj, name,
2075                                object_get_typename(target), target,
2076                                NULL, OBJ_PROP_LINK_DIRECT);
2077}
2078
2079const char *object_get_canonical_path_component(const Object *obj)
2080{
2081    ObjectProperty *prop = NULL;
2082    GHashTableIter iter;
2083
2084    if (obj->parent == NULL) {
2085        return NULL;
2086    }
2087
2088    g_hash_table_iter_init(&iter, obj->parent->properties);
2089    while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&prop)) {
2090        if (!object_property_is_child(prop)) {
2091            continue;
2092        }
2093
2094        if (prop->opaque == obj) {
2095            return prop->name;
2096        }
2097    }
2098
2099    /* obj had a parent but was not a child, should never happen */
2100    g_assert_not_reached();
2101}
2102
2103char *object_get_canonical_path(const Object *obj)
2104{
2105    Object *root = object_get_root();
2106    char *newpath, *path = NULL;
2107
2108    if (obj == root) {
2109        return g_strdup("/");
2110    }
2111
2112    do {
2113        const char *component = object_get_canonical_path_component(obj);
2114
2115        if (!component) {
2116            /* A canonical path must be complete, so discard what was
2117             * collected so far.
2118             */
2119            g_free(path);
2120            return NULL;
2121        }
2122
2123        newpath = g_strdup_printf("/%s%s", component, path ? path : "");
2124        g_free(path);
2125        path = newpath;
2126        obj = obj->parent;
2127    } while (obj != root);
2128
2129    return path;
2130}
2131
2132Object *object_resolve_path_component(Object *parent, const char *part)
2133{
2134    ObjectProperty *prop = object_property_find(parent, part);
2135    if (prop == NULL) {
2136        return NULL;
2137    }
2138
2139    if (prop->resolve) {
2140        return prop->resolve(parent, prop->opaque, part);
2141    } else {
2142        return NULL;
2143    }
2144}
2145
2146static Object *object_resolve_abs_path(Object *parent,
2147                                          char **parts,
2148                                          const char *typename)
2149{
2150    Object *child;
2151
2152    if (*parts == NULL) {
2153        return object_dynamic_cast(parent, typename);
2154    }
2155
2156    if (strcmp(*parts, "") == 0) {
2157        return object_resolve_abs_path(parent, parts + 1, typename);
2158    }
2159
2160    child = object_resolve_path_component(parent, *parts);
2161    if (!child) {
2162        return NULL;
2163    }
2164
2165    return object_resolve_abs_path(child, parts + 1, typename);
2166}
2167
2168static Object *object_resolve_partial_path(Object *parent,
2169                                           char **parts,
2170                                           const char *typename,
2171                                           bool *ambiguous)
2172{
2173    Object *obj;
2174    GHashTableIter iter;
2175    ObjectProperty *prop;
2176
2177    obj = object_resolve_abs_path(parent, parts, typename);
2178
2179    g_hash_table_iter_init(&iter, parent->properties);
2180    while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&prop)) {
2181        Object *found;
2182
2183        if (!object_property_is_child(prop)) {
2184            continue;
2185        }
2186
2187        found = object_resolve_partial_path(prop->opaque, parts,
2188                                            typename, ambiguous);
2189        if (found) {
2190            if (obj) {
2191                *ambiguous = true;
2192                return NULL;
2193            }
2194            obj = found;
2195        }
2196
2197        if (*ambiguous) {
2198            return NULL;
2199        }
2200    }
2201
2202    return obj;
2203}
2204
2205Object *object_resolve_path_type(const char *path, const char *typename,
2206                                 bool *ambiguous)
2207{
2208    Object *obj;
2209    char **parts;
2210
2211    parts = g_strsplit(path, "/", 0);
2212    assert(parts);
2213
2214    if (parts[0] == NULL || strcmp(parts[0], "") != 0) {
2215        bool ambig = false;
2216        obj = object_resolve_partial_path(object_get_root(), parts,
2217                                          typename, &ambig);
2218        if (ambiguous) {
2219            *ambiguous = ambig;
2220        }
2221    } else {
2222        obj = object_resolve_abs_path(object_get_root(), parts + 1, typename);
2223        if (ambiguous) {
2224            *ambiguous = false;
2225        }
2226    }
2227
2228    g_strfreev(parts);
2229
2230    return obj;
2231}
2232
2233Object *object_resolve_path(const char *path, bool *ambiguous)
2234{
2235    return object_resolve_path_type(path, TYPE_OBJECT, ambiguous);
2236}
2237
2238Object *object_resolve_path_at(Object *parent, const char *path)
2239{
2240    g_auto(GStrv) parts = g_strsplit(path, "/", 0);
2241
2242    if (*path == '/') {
2243        return object_resolve_abs_path(object_get_root(), parts + 1,
2244                                       TYPE_OBJECT);
2245    }
2246    return object_resolve_abs_path(parent, parts, TYPE_OBJECT);
2247}
2248
2249Object *object_resolve_type_unambiguous(const char *typename, Error **errp)
2250{
2251    bool ambig = false;
2252    Object *o = object_resolve_path_type("", typename, &ambig);
2253
2254    if (ambig) {
2255        error_setg(errp, "More than one object of type %s", typename);
2256        return NULL;
2257    }
2258    if (!o) {
2259        error_setg(errp, "No object found of type %s", typename);
2260        return NULL;
2261    }
2262    return o;
2263}
2264
2265typedef struct StringProperty
2266{
2267    char *(*get)(Object *, Error **);
2268    void (*set)(Object *, const char *, Error **);
2269} StringProperty;
2270
2271static void property_get_str(Object *obj, Visitor *v, const char *name,
2272                             void *opaque, Error **errp)
2273{
2274    StringProperty *prop = opaque;
2275    char *value;
2276    Error *err = NULL;
2277
2278    value = prop->get(obj, &err);
2279    if (err) {
2280        error_propagate(errp, err);
2281        return;
2282    }
2283
2284    visit_type_str(v, name, &value, errp);
2285    g_free(value);
2286}
2287
2288static void property_set_str(Object *obj, Visitor *v, const char *name,
2289                             void *opaque, Error **errp)
2290{
2291    StringProperty *prop = opaque;
2292    char *value;
2293
2294    if (!visit_type_str(v, name, &value, errp)) {
2295        return;
2296    }
2297
2298    prop->set(obj, value, errp);
2299    g_free(value);
2300}
2301
2302static void property_release_data(Object *obj, const char *name,
2303                                  void *opaque)
2304{
2305    g_free(opaque);
2306}
2307
2308ObjectProperty *
2309object_property_add_str(Object *obj, const char *name,
2310                        char *(*get)(Object *, Error **),
2311                        void (*set)(Object *, const char *, Error **))
2312{
2313    StringProperty *prop = g_malloc0(sizeof(*prop));
2314
2315    prop->get = get;
2316    prop->set = set;
2317
2318    return object_property_add(obj, name, "string",
2319                               get ? property_get_str : NULL,
2320                               set ? property_set_str : NULL,
2321                               property_release_data,
2322                               prop);
2323}
2324
2325ObjectProperty *
2326object_class_property_add_str(ObjectClass *klass, const char *name,
2327                                   char *(*get)(Object *, Error **),
2328                                   void (*set)(Object *, const char *,
2329                                               Error **))
2330{
2331    StringProperty *prop = g_malloc0(sizeof(*prop));
2332
2333    prop->get = get;
2334    prop->set = set;
2335
2336    return object_class_property_add(klass, name, "string",
2337                                     get ? property_get_str : NULL,
2338                                     set ? property_set_str : NULL,
2339                                     NULL,
2340                                     prop);
2341}
2342
2343typedef struct BoolProperty
2344{
2345    bool (*get)(Object *, Error **);
2346    void (*set)(Object *, bool, Error **);
2347} BoolProperty;
2348
2349static void property_get_bool(Object *obj, Visitor *v, const char *name,
2350                              void *opaque, Error **errp)
2351{
2352    BoolProperty *prop = opaque;
2353    bool value;
2354    Error *err = NULL;
2355
2356    value = prop->get(obj, &err);
2357    if (err) {
2358        error_propagate(errp, err);
2359        return;
2360    }
2361
2362    visit_type_bool(v, name, &value, errp);
2363}
2364
2365static void property_set_bool(Object *obj, Visitor *v, const char *name,
2366                              void *opaque, Error **errp)
2367{
2368    BoolProperty *prop = opaque;
2369    bool value;
2370
2371    if (!visit_type_bool(v, name, &value, errp)) {
2372        return;
2373    }
2374
2375    prop->set(obj, value, errp);
2376}
2377
2378ObjectProperty *
2379object_property_add_bool(Object *obj, const char *name,
2380                         bool (*get)(Object *, Error **),
2381                         void (*set)(Object *, bool, Error **))
2382{
2383    BoolProperty *prop = g_malloc0(sizeof(*prop));
2384
2385    prop->get = get;
2386    prop->set = set;
2387
2388    return object_property_add(obj, name, "bool",
2389                               get ? property_get_bool : NULL,
2390                               set ? property_set_bool : NULL,
2391                               property_release_data,
2392                               prop);
2393}
2394
2395ObjectProperty *
2396object_class_property_add_bool(ObjectClass *klass, const char *name,
2397                                    bool (*get)(Object *, Error **),
2398                                    void (*set)(Object *, bool, Error **))
2399{
2400    BoolProperty *prop = g_malloc0(sizeof(*prop));
2401
2402    prop->get = get;
2403    prop->set = set;
2404
2405    return object_class_property_add(klass, name, "bool",
2406                                     get ? property_get_bool : NULL,
2407                                     set ? property_set_bool : NULL,
2408                                     NULL,
2409                                     prop);
2410}
2411
2412static void property_get_enum(Object *obj, Visitor *v, const char *name,
2413                              void *opaque, Error **errp)
2414{
2415    EnumProperty *prop = opaque;
2416    int value;
2417    Error *err = NULL;
2418
2419    value = prop->get(obj, &err);
2420    if (err) {
2421        error_propagate(errp, err);
2422        return;
2423    }
2424
2425    visit_type_enum(v, name, &value, prop->lookup, errp);
2426}
2427
2428static void property_set_enum(Object *obj, Visitor *v, const char *name,
2429                              void *opaque, Error **errp)
2430{
2431    EnumProperty *prop = opaque;
2432    int value;
2433
2434    if (!visit_type_enum(v, name, &value, prop->lookup, errp)) {
2435        return;
2436    }
2437    prop->set(obj, value, errp);
2438}
2439
2440ObjectProperty *
2441object_property_add_enum(Object *obj, const char *name,
2442                         const char *typename,
2443                         const QEnumLookup *lookup,
2444                         int (*get)(Object *, Error **),
2445                         void (*set)(Object *, int, Error **))
2446{
2447    EnumProperty *prop = g_malloc(sizeof(*prop));
2448
2449    prop->lookup = lookup;
2450    prop->get = get;
2451    prop->set = set;
2452
2453    return object_property_add(obj, name, typename,
2454                               get ? property_get_enum : NULL,
2455                               set ? property_set_enum : NULL,
2456                               property_release_data,
2457                               prop);
2458}
2459
2460ObjectProperty *
2461object_class_property_add_enum(ObjectClass *klass, const char *name,
2462                                    const char *typename,
2463                                    const QEnumLookup *lookup,
2464                                    int (*get)(Object *, Error **),
2465                                    void (*set)(Object *, int, Error **))
2466{
2467    EnumProperty *prop = g_malloc(sizeof(*prop));
2468
2469    prop->lookup = lookup;
2470    prop->get = get;
2471    prop->set = set;
2472
2473    return object_class_property_add(klass, name, typename,
2474                                     get ? property_get_enum : NULL,
2475                                     set ? property_set_enum : NULL,
2476                                     NULL,
2477                                     prop);
2478}
2479
2480typedef struct TMProperty {
2481    void (*get)(Object *, struct tm *, Error **);
2482} TMProperty;
2483
2484static void property_get_tm(Object *obj, Visitor *v, const char *name,
2485                            void *opaque, Error **errp)
2486{
2487    TMProperty *prop = opaque;
2488    Error *err = NULL;
2489    struct tm value;
2490
2491    prop->get(obj, &value, &err);
2492    if (err) {
2493        error_propagate(errp, err);
2494        return;
2495    }
2496
2497    if (!visit_start_struct(v, name, NULL, 0, errp)) {
2498        return;
2499    }
2500    if (!visit_type_int32(v, "tm_year", &value.tm_year, errp)) {
2501        goto out_end;
2502    }
2503    if (!visit_type_int32(v, "tm_mon", &value.tm_mon, errp)) {
2504        goto out_end;
2505    }
2506    if (!visit_type_int32(v, "tm_mday", &value.tm_mday, errp)) {
2507        goto out_end;
2508    }
2509    if (!visit_type_int32(v, "tm_hour", &value.tm_hour, errp)) {
2510        goto out_end;
2511    }
2512    if (!visit_type_int32(v, "tm_min", &value.tm_min, errp)) {
2513        goto out_end;
2514    }
2515    if (!visit_type_int32(v, "tm_sec", &value.tm_sec, errp)) {
2516        goto out_end;
2517    }
2518    visit_check_struct(v, errp);
2519out_end:
2520    visit_end_struct(v, NULL);
2521}
2522
2523ObjectProperty *
2524object_property_add_tm(Object *obj, const char *name,
2525                       void (*get)(Object *, struct tm *, Error **))
2526{
2527    TMProperty *prop = g_malloc0(sizeof(*prop));
2528
2529    prop->get = get;
2530
2531    return object_property_add(obj, name, "struct tm",
2532                               get ? property_get_tm : NULL, NULL,
2533                               property_release_data,
2534                               prop);
2535}
2536
2537ObjectProperty *
2538object_class_property_add_tm(ObjectClass *klass, const char *name,
2539                             void (*get)(Object *, struct tm *, Error **))
2540{
2541    TMProperty *prop = g_malloc0(sizeof(*prop));
2542
2543    prop->get = get;
2544
2545    return object_class_property_add(klass, name, "struct tm",
2546                                     get ? property_get_tm : NULL,
2547                                     NULL, NULL, prop);
2548}
2549
2550static char *object_get_type(Object *obj, Error **errp)
2551{
2552    return g_strdup(object_get_typename(obj));
2553}
2554
2555static void property_get_uint8_ptr(Object *obj, Visitor *v, const char *name,
2556                                   void *opaque, Error **errp)
2557{
2558    uint8_t value = *(uint8_t *)opaque;
2559    visit_type_uint8(v, name, &value, errp);
2560}
2561
2562static void property_set_uint8_ptr(Object *obj, Visitor *v, const char *name,
2563                                   void *opaque, Error **errp)
2564{
2565    uint8_t *field = opaque;
2566    uint8_t value;
2567
2568    if (!visit_type_uint8(v, name, &value, errp)) {
2569        return;
2570    }
2571
2572    *field = value;
2573}
2574
2575static void property_get_uint16_ptr(Object *obj, Visitor *v, const char *name,
2576                                    void *opaque, Error **errp)
2577{
2578    uint16_t value = *(uint16_t *)opaque;
2579    visit_type_uint16(v, name, &value, errp);
2580}
2581
2582static void property_set_uint16_ptr(Object *obj, Visitor *v, const char *name,
2583                                    void *opaque, Error **errp)
2584{
2585    uint16_t *field = opaque;
2586    uint16_t value;
2587
2588    if (!visit_type_uint16(v, name, &value, errp)) {
2589        return;
2590    }
2591
2592    *field = value;
2593}
2594
2595static void property_get_uint32_ptr(Object *obj, Visitor *v, const char *name,
2596                                    void *opaque, Error **errp)
2597{
2598    uint32_t value = *(uint32_t *)opaque;
2599    visit_type_uint32(v, name, &value, errp);
2600}
2601
2602static void property_set_uint32_ptr(Object *obj, Visitor *v, const char *name,
2603                                    void *opaque, Error **errp)
2604{
2605    uint32_t *field = opaque;
2606    uint32_t value;
2607
2608    if (!visit_type_uint32(v, name, &value, errp)) {
2609        return;
2610    }
2611
2612    *field = value;
2613}
2614
2615static void property_get_uint64_ptr(Object *obj, Visitor *v, const char *name,
2616                                    void *opaque, Error **errp)
2617{
2618    uint64_t value = *(uint64_t *)opaque;
2619    visit_type_uint64(v, name, &value, errp);
2620}
2621
2622static void property_set_uint64_ptr(Object *obj, Visitor *v, const char *name,
2623                                    void *opaque, Error **errp)
2624{
2625    uint64_t *field = opaque;
2626    uint64_t value;
2627
2628    if (!visit_type_uint64(v, name, &value, errp)) {
2629        return;
2630    }
2631
2632    *field = value;
2633}
2634
2635ObjectProperty *
2636object_property_add_uint8_ptr(Object *obj, const char *name,
2637                              const uint8_t *v,
2638                              ObjectPropertyFlags flags)
2639{
2640    ObjectPropertyAccessor *getter = NULL;
2641    ObjectPropertyAccessor *setter = NULL;
2642
2643    if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) {
2644        getter = property_get_uint8_ptr;
2645    }
2646
2647    if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) {
2648        setter = property_set_uint8_ptr;
2649    }
2650
2651    return object_property_add(obj, name, "uint8",
2652                               getter, setter, NULL, (void *)v);
2653}
2654
2655ObjectProperty *
2656object_class_property_add_uint8_ptr(ObjectClass *klass, const char *name,
2657                                    const uint8_t *v,
2658                                    ObjectPropertyFlags flags)
2659{
2660    ObjectPropertyAccessor *getter = NULL;
2661    ObjectPropertyAccessor *setter = NULL;
2662
2663    if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) {
2664        getter = property_get_uint8_ptr;
2665    }
2666
2667    if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) {
2668        setter = property_set_uint8_ptr;
2669    }
2670
2671    return object_class_property_add(klass, name, "uint8",
2672                                     getter, setter, NULL, (void *)v);
2673}
2674
2675ObjectProperty *
2676object_property_add_uint16_ptr(Object *obj, const char *name,
2677                               const uint16_t *v,
2678                               ObjectPropertyFlags flags)
2679{
2680    ObjectPropertyAccessor *getter = NULL;
2681    ObjectPropertyAccessor *setter = NULL;
2682
2683    if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) {
2684        getter = property_get_uint16_ptr;
2685    }
2686
2687    if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) {
2688        setter = property_set_uint16_ptr;
2689    }
2690
2691    return object_property_add(obj, name, "uint16",
2692                               getter, setter, NULL, (void *)v);
2693}
2694
2695ObjectProperty *
2696object_class_property_add_uint16_ptr(ObjectClass *klass, const char *name,
2697                                     const uint16_t *v,
2698                                     ObjectPropertyFlags flags)
2699{
2700    ObjectPropertyAccessor *getter = NULL;
2701    ObjectPropertyAccessor *setter = NULL;
2702
2703    if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) {
2704        getter = property_get_uint16_ptr;
2705    }
2706
2707    if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) {
2708        setter = property_set_uint16_ptr;
2709    }
2710
2711    return object_class_property_add(klass, name, "uint16",
2712                                     getter, setter, NULL, (void *)v);
2713}
2714
2715ObjectProperty *
2716object_property_add_uint32_ptr(Object *obj, const char *name,
2717                               const uint32_t *v,
2718                               ObjectPropertyFlags flags)
2719{
2720    ObjectPropertyAccessor *getter = NULL;
2721    ObjectPropertyAccessor *setter = NULL;
2722
2723    if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) {
2724        getter = property_get_uint32_ptr;
2725    }
2726
2727    if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) {
2728        setter = property_set_uint32_ptr;
2729    }
2730
2731    return object_property_add(obj, name, "uint32",
2732                               getter, setter, NULL, (void *)v);
2733}
2734
2735ObjectProperty *
2736object_class_property_add_uint32_ptr(ObjectClass *klass, const char *name,
2737                                     const uint32_t *v,
2738                                     ObjectPropertyFlags flags)
2739{
2740    ObjectPropertyAccessor *getter = NULL;
2741    ObjectPropertyAccessor *setter = NULL;
2742
2743    if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) {
2744        getter = property_get_uint32_ptr;
2745    }
2746
2747    if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) {
2748        setter = property_set_uint32_ptr;
2749    }
2750
2751    return object_class_property_add(klass, name, "uint32",
2752                                     getter, setter, NULL, (void *)v);
2753}
2754
2755ObjectProperty *
2756object_property_add_uint64_ptr(Object *obj, const char *name,
2757                               const uint64_t *v,
2758                               ObjectPropertyFlags flags)
2759{
2760    ObjectPropertyAccessor *getter = NULL;
2761    ObjectPropertyAccessor *setter = NULL;
2762
2763    if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) {
2764        getter = property_get_uint64_ptr;
2765    }
2766
2767    if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) {
2768        setter = property_set_uint64_ptr;
2769    }
2770
2771    return object_property_add(obj, name, "uint64",
2772                               getter, setter, NULL, (void *)v);
2773}
2774
2775ObjectProperty *
2776object_class_property_add_uint64_ptr(ObjectClass *klass, const char *name,
2777                                     const uint64_t *v,
2778                                     ObjectPropertyFlags flags)
2779{
2780    ObjectPropertyAccessor *getter = NULL;
2781    ObjectPropertyAccessor *setter = NULL;
2782
2783    if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) {
2784        getter = property_get_uint64_ptr;
2785    }
2786
2787    if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) {
2788        setter = property_set_uint64_ptr;
2789    }
2790
2791    return object_class_property_add(klass, name, "uint64",
2792                                     getter, setter, NULL, (void *)v);
2793}
2794
2795typedef struct {
2796    Object *target_obj;
2797    char *target_name;
2798} AliasProperty;
2799
2800static void property_get_alias(Object *obj, Visitor *v, const char *name,
2801                               void *opaque, Error **errp)
2802{
2803    AliasProperty *prop = opaque;
2804    Visitor *alias_v = visitor_forward_field(v, prop->target_name, name);
2805
2806    object_property_get(prop->target_obj, prop->target_name, alias_v, errp);
2807    visit_free(alias_v);
2808}
2809
2810static void property_set_alias(Object *obj, Visitor *v, const char *name,
2811                               void *opaque, Error **errp)
2812{
2813    AliasProperty *prop = opaque;
2814    Visitor *alias_v = visitor_forward_field(v, prop->target_name, name);
2815
2816    object_property_set(prop->target_obj, prop->target_name, alias_v, errp);
2817    visit_free(alias_v);
2818}
2819
2820static Object *property_resolve_alias(Object *obj, void *opaque,
2821                                      const char *part)
2822{
2823    AliasProperty *prop = opaque;
2824
2825    return object_resolve_path_component(prop->target_obj, prop->target_name);
2826}
2827
2828static void property_release_alias(Object *obj, const char *name, void *opaque)
2829{
2830    AliasProperty *prop = opaque;
2831
2832    g_free(prop->target_name);
2833    g_free(prop);
2834}
2835
2836ObjectProperty *
2837object_property_add_alias(Object *obj, const char *name,
2838                          Object *target_obj, const char *target_name)
2839{
2840    AliasProperty *prop;
2841    ObjectProperty *op;
2842    ObjectProperty *target_prop;
2843    g_autofree char *prop_type = NULL;
2844
2845    target_prop = object_property_find_err(target_obj, target_name,
2846                                           &error_abort);
2847
2848    if (object_property_is_child(target_prop)) {
2849        prop_type = g_strdup_printf("link%s",
2850                                    target_prop->type + strlen("child"));
2851    } else {
2852        prop_type = g_strdup(target_prop->type);
2853    }
2854
2855    prop = g_malloc(sizeof(*prop));
2856    prop->target_obj = target_obj;
2857    prop->target_name = g_strdup(target_name);
2858
2859    op = object_property_add(obj, name, prop_type,
2860                             property_get_alias,
2861                             property_set_alias,
2862                             property_release_alias,
2863                             prop);
2864    op->resolve = property_resolve_alias;
2865    if (target_prop->defval) {
2866        op->defval = qobject_ref(target_prop->defval);
2867    }
2868
2869    object_property_set_description(obj, op->name,
2870                                    target_prop->description);
2871    return op;
2872}
2873
2874void object_property_set_description(Object *obj, const char *name,
2875                                     const char *description)
2876{
2877    ObjectProperty *op;
2878
2879    op = object_property_find_err(obj, name, &error_abort);
2880    g_free(op->description);
2881    op->description = g_strdup(description);
2882}
2883
2884void object_class_property_set_description(ObjectClass *klass,
2885                                           const char *name,
2886                                           const char *description)
2887{
2888    ObjectProperty *op;
2889
2890    op = g_hash_table_lookup(klass->properties, name);
2891    g_free(op->description);
2892    op->description = g_strdup(description);
2893}
2894
2895static void object_class_init(ObjectClass *klass, const void *data)
2896{
2897    object_class_property_add_str(klass, "type", object_get_type,
2898                                  NULL);
2899}
2900
2901static void register_types(void)
2902{
2903    static const TypeInfo interface_info = {
2904        .name = TYPE_INTERFACE,
2905        .class_size = sizeof(InterfaceClass),
2906        .abstract = true,
2907    };
2908
2909    static const TypeInfo object_info = {
2910        .name = TYPE_OBJECT,
2911        .instance_size = sizeof(Object),
2912        .class_init = object_class_init,
2913        .abstract = true,
2914    };
2915
2916    type_interface = type_register_internal(&interface_info);
2917    type_register_internal(&object_info);
2918}
2919
2920type_init(register_types)
2921