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