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