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/object.h"
  14#include "qemu-common.h"
  15#include "qapi/qapi-visit-core.h"
  16#include "qapi/string-input-visitor.h"
  17#include "qapi/string-output-visitor.h"
  18
  19/* TODO: replace QObject with a simpler visitor to avoid a dependency
  20 * of the QOM core on QObject?  */
  21#include "qemu/qom-qobject.h"
  22#include "qobject.h"
  23#include "qbool.h"
  24#include "qint.h"
  25#include "qstring.h"
  26
  27#define MAX_INTERFACES 32
  28
  29typedef struct InterfaceImpl InterfaceImpl;
  30typedef struct TypeImpl TypeImpl;
  31
  32struct InterfaceImpl
  33{
  34    const char *parent;
  35    void (*interface_initfn)(ObjectClass *class, void *data);
  36    TypeImpl *type;
  37};
  38
  39struct TypeImpl
  40{
  41    const char *name;
  42
  43    size_t class_size;
  44
  45    size_t instance_size;
  46
  47    void (*class_init)(ObjectClass *klass, void *data);
  48    void (*class_finalize)(ObjectClass *klass, void *data);
  49
  50    void *class_data;
  51
  52    void (*instance_init)(Object *obj);
  53    void (*instance_finalize)(Object *obj);
  54
  55    bool abstract;
  56
  57    const char *parent;
  58    TypeImpl *parent_type;
  59
  60    ObjectClass *class;
  61
  62    int num_interfaces;
  63    InterfaceImpl interfaces[MAX_INTERFACES];
  64};
  65
  66typedef struct Interface
  67{
  68    Object parent;
  69    Object *obj;
  70} Interface;
  71
  72#define INTERFACE(obj) OBJECT_CHECK(Interface, obj, TYPE_INTERFACE)
  73
  74static Type type_interface;
  75
  76static GHashTable *type_table_get(void)
  77{
  78    static GHashTable *type_table;
  79
  80    if (type_table == NULL) {
  81        type_table = g_hash_table_new(g_str_hash, g_str_equal);
  82    }
  83
  84    return type_table;
  85}
  86
  87static void type_table_add(TypeImpl *ti)
  88{
  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
  97TypeImpl *type_register(const TypeInfo *info)
  98{
  99    TypeImpl *ti = g_malloc0(sizeof(*ti));
 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_finalize = info->class_finalize;
 116    ti->class_data = info->class_data;
 117
 118    ti->instance_init = info->instance_init;
 119    ti->instance_finalize = info->instance_finalize;
 120
 121    ti->abstract = info->abstract;
 122
 123    if (info->interfaces) {
 124        int i;
 125
 126        for (i = 0; info->interfaces[i].type; i++) {
 127            ti->interfaces[i].parent = info->interfaces[i].type;
 128            ti->interfaces[i].interface_initfn = info->interfaces[i].interface_initfn;
 129            ti->num_interfaces++;
 130        }
 131    }
 132
 133    type_table_add(ti);
 134
 135    return ti;
 136}
 137
 138TypeImpl *type_register_static(const TypeInfo *info)
 139{
 140    return type_register(info);
 141}
 142
 143static TypeImpl *type_get_by_name(const char *name)
 144{
 145    if (name == NULL) {
 146        return NULL;
 147    }
 148
 149    return type_table_lookup(name);
 150}
 151
 152static TypeImpl *type_get_parent(TypeImpl *type)
 153{
 154    if (!type->parent_type && type->parent) {
 155        type->parent_type = type_get_by_name(type->parent);
 156        g_assert(type->parent_type != NULL);
 157    }
 158
 159    return type->parent_type;
 160}
 161
 162static bool type_has_parent(TypeImpl *type)
 163{
 164    return (type->parent != NULL);
 165}
 166
 167static size_t type_class_get_size(TypeImpl *ti)
 168{
 169    if (ti->class_size) {
 170        return ti->class_size;
 171    }
 172
 173    if (type_has_parent(ti)) {
 174        return type_class_get_size(type_get_parent(ti));
 175    }
 176
 177    return sizeof(ObjectClass);
 178}
 179
 180static size_t type_object_get_size(TypeImpl *ti)
 181{
 182    if (ti->instance_size) {
 183        return ti->instance_size;
 184    }
 185
 186    if (type_has_parent(ti)) {
 187        return type_object_get_size(type_get_parent(ti));
 188    }
 189
 190    return 0;
 191}
 192
 193static void type_class_interface_init(TypeImpl *ti, InterfaceImpl *iface)
 194{
 195    TypeInfo info = {
 196        .instance_size = sizeof(Interface),
 197        .parent = iface->parent,
 198        .class_size = sizeof(InterfaceClass),
 199        .class_init = iface->interface_initfn,
 200        .abstract = true,
 201    };
 202    char *name = g_strdup_printf("<%s::%s>", ti->name, iface->parent);
 203
 204    info.name = name;
 205    iface->type = type_register(&info);
 206    g_free(name);
 207}
 208
 209static void type_initialize(TypeImpl *ti)
 210{
 211    size_t class_size = sizeof(ObjectClass);
 212    int i;
 213
 214    if (ti->class) {
 215        return;
 216    }
 217
 218    ti->class_size = type_class_get_size(ti);
 219    ti->instance_size = type_object_get_size(ti);
 220
 221    ti->class = g_malloc0(ti->class_size);
 222    ti->class->type = ti;
 223
 224    if (type_has_parent(ti)) {
 225        TypeImpl *parent = type_get_parent(ti);
 226
 227        type_initialize(parent);
 228
 229        class_size = parent->class_size;
 230        g_assert(parent->class_size <= ti->class_size);
 231
 232        memcpy((void *)ti->class + sizeof(ObjectClass),
 233               (void *)parent->class + sizeof(ObjectClass),
 234               parent->class_size - sizeof(ObjectClass));
 235    }
 236
 237    memset((void *)ti->class + class_size, 0, ti->class_size - class_size);
 238
 239    for (i = 0; i < ti->num_interfaces; i++) {
 240        type_class_interface_init(ti, &ti->interfaces[i]);
 241    }
 242
 243    if (ti->class_init) {
 244        ti->class_init(ti->class, ti->class_data);
 245    }
 246}
 247
 248static void object_interface_init(Object *obj, InterfaceImpl *iface)
 249{
 250    TypeImpl *ti = iface->type;
 251    Interface *iface_obj;
 252
 253    iface_obj = INTERFACE(object_new(ti->name));
 254    iface_obj->obj = obj;
 255
 256    obj->interfaces = g_slist_prepend(obj->interfaces, iface_obj);
 257}
 258
 259static void object_init_with_type(Object *obj, TypeImpl *ti)
 260{
 261    int i;
 262
 263    if (type_has_parent(ti)) {
 264        object_init_with_type(obj, type_get_parent(ti));
 265    }
 266
 267    for (i = 0; i < ti->num_interfaces; i++) {
 268        object_interface_init(obj, &ti->interfaces[i]);
 269    }
 270
 271    if (ti->instance_init) {
 272        ti->instance_init(obj);
 273    }
 274}
 275
 276void object_initialize_with_type(void *data, TypeImpl *type)
 277{
 278    Object *obj = data;
 279
 280    g_assert(type != NULL);
 281    type_initialize(type);
 282
 283    g_assert(type->instance_size >= sizeof(Object));
 284    g_assert(type->abstract == false);
 285
 286    memset(obj, 0, type->instance_size);
 287    obj->class = type->class;
 288    QTAILQ_INIT(&obj->properties);
 289    object_init_with_type(obj, type);
 290}
 291
 292void object_initialize(void *data, const char *typename)
 293{
 294    TypeImpl *type = type_get_by_name(typename);
 295
 296    object_initialize_with_type(data, type);
 297}
 298
 299static void object_property_del_all(Object *obj)
 300{
 301    while (!QTAILQ_EMPTY(&obj->properties)) {
 302        ObjectProperty *prop = QTAILQ_FIRST(&obj->properties);
 303
 304        QTAILQ_REMOVE(&obj->properties, prop, node);
 305
 306        if (prop->release) {
 307            prop->release(obj, prop->name, prop->opaque);
 308        }
 309
 310        g_free(prop->name);
 311        g_free(prop->type);
 312        g_free(prop);
 313    }
 314}
 315
 316static void object_property_del_child(Object *obj, Object *child, Error **errp)
 317{
 318    ObjectProperty *prop;
 319
 320    QTAILQ_FOREACH(prop, &obj->properties, node) {
 321        if (strstart(prop->type, "child<", NULL) && prop->opaque == child) {
 322            object_property_del(obj, prop->name, errp);
 323            break;
 324        }
 325    }
 326}
 327
 328void object_unparent(Object *obj)
 329{
 330    if (obj->parent) {
 331        object_property_del_child(obj->parent, obj, NULL);
 332    }
 333}
 334
 335static void object_deinit(Object *obj, TypeImpl *type)
 336{
 337    if (type->instance_finalize) {
 338        type->instance_finalize(obj);
 339    }
 340
 341    while (obj->interfaces) {
 342        Interface *iface_obj = obj->interfaces->data;
 343        obj->interfaces = g_slist_delete_link(obj->interfaces, obj->interfaces);
 344        object_delete(OBJECT(iface_obj));
 345    }
 346
 347    if (type_has_parent(type)) {
 348        object_deinit(obj, type_get_parent(type));
 349    }
 350
 351    object_unparent(obj);
 352}
 353
 354void object_finalize(void *data)
 355{
 356    Object *obj = data;
 357    TypeImpl *ti = obj->class->type;
 358
 359    object_deinit(obj, ti);
 360    object_property_del_all(obj);
 361
 362    g_assert(obj->ref == 0);
 363}
 364
 365Object *object_new_with_type(Type type)
 366{
 367    Object *obj;
 368
 369    g_assert(type != NULL);
 370    type_initialize(type);
 371
 372    obj = g_malloc(type->instance_size);
 373    object_initialize_with_type(obj, type);
 374    object_ref(obj);
 375
 376    return obj;
 377}
 378
 379Object *object_new(const char *typename)
 380{
 381    TypeImpl *ti = type_get_by_name(typename);
 382
 383    return object_new_with_type(ti);
 384}
 385
 386void object_delete(Object *obj)
 387{
 388    object_unref(obj);
 389    g_assert(obj->ref == 0);
 390    g_free(obj);
 391}
 392
 393static bool type_is_ancestor(TypeImpl *type, TypeImpl *target_type)
 394{
 395    assert(target_type);
 396
 397    /* Check if typename is a direct ancestor of type */
 398    while (type) {
 399        if (type == target_type) {
 400            return true;
 401        }
 402
 403        type = type_get_parent(type);
 404    }
 405
 406    return false;
 407}
 408
 409static bool object_is_type(Object *obj, TypeImpl *target_type)
 410{
 411    return !target_type || type_is_ancestor(obj->class->type, target_type);
 412}
 413
 414Object *object_dynamic_cast(Object *obj, const char *typename)
 415{
 416    TypeImpl *target_type = type_get_by_name(typename);
 417    GSList *i;
 418
 419    /* Check if typename is a direct ancestor.  Special-case TYPE_OBJECT,
 420     * we want to go back from interfaces to the parent.
 421    */
 422    if (target_type && object_is_type(obj, target_type)) {
 423        return obj;
 424    }
 425
 426    /* Check if obj is an interface and its containing object is a direct
 427     * ancestor of typename.  In principle we could do this test at the very
 428     * beginning of object_dynamic_cast, avoiding a second call to
 429     * object_is_type.  However, casting between interfaces is relatively
 430     * rare, and object_is_type(obj, type_interface) would fail almost always.
 431     *
 432     * Perhaps we could add a magic value to the object header for increased
 433     * (run-time) type safety and to speed up tests like this one.  If we ever
 434     * do that we can revisit the order here.
 435     */
 436    if (object_is_type(obj, type_interface)) {
 437        assert(!obj->interfaces);
 438        obj = INTERFACE(obj)->obj;
 439        if (object_is_type(obj, target_type)) {
 440            return obj;
 441        }
 442    }
 443
 444    if (!target_type) {
 445        return obj;
 446    }
 447
 448    /* Check if obj has an interface of typename */
 449    for (i = obj->interfaces; i; i = i->next) {
 450        Interface *iface = i->data;
 451
 452        if (object_is_type(OBJECT(iface), target_type)) {
 453            return OBJECT(iface);
 454        }
 455    }
 456
 457    return NULL;
 458}
 459
 460
 461static void register_types(void)
 462{
 463    static TypeInfo interface_info = {
 464        .name = TYPE_INTERFACE,
 465        .instance_size = sizeof(Interface),
 466        .abstract = true,
 467    };
 468
 469    type_interface = type_register_static(&interface_info);
 470}
 471
 472type_init(register_types)
 473
 474Object *object_dynamic_cast_assert(Object *obj, const char *typename)
 475{
 476    Object *inst;
 477
 478    inst = object_dynamic_cast(obj, typename);
 479
 480    if (!inst) {
 481        fprintf(stderr, "Object %p is not an instance of type %s\n",
 482                obj, typename);
 483        abort();
 484    }
 485
 486    return inst;
 487}
 488
 489ObjectClass *object_class_dynamic_cast(ObjectClass *class,
 490                                       const char *typename)
 491{
 492    TypeImpl *target_type = type_get_by_name(typename);
 493    TypeImpl *type = class->type;
 494
 495    while (type) {
 496        if (type == target_type) {
 497            return class;
 498        }
 499
 500        type = type_get_parent(type);
 501    }
 502
 503    return NULL;
 504}
 505
 506ObjectClass *object_class_dynamic_cast_assert(ObjectClass *class,
 507                                              const char *typename)
 508{
 509    ObjectClass *ret = object_class_dynamic_cast(class, typename);
 510
 511    if (!ret) {
 512        fprintf(stderr, "Object %p is not an instance of type %s\n",
 513                class, typename);
 514        abort();
 515    }
 516
 517    return ret;
 518}
 519
 520const char *object_get_typename(Object *obj)
 521{
 522    return obj->class->type->name;
 523}
 524
 525ObjectClass *object_get_class(Object *obj)
 526{
 527    return obj->class;
 528}
 529
 530const char *object_class_get_name(ObjectClass *klass)
 531{
 532    return klass->type->name;
 533}
 534
 535ObjectClass *object_class_by_name(const char *typename)
 536{
 537    TypeImpl *type = type_get_by_name(typename);
 538
 539    if (!type) {
 540        return NULL;
 541    }
 542
 543    type_initialize(type);
 544
 545    return type->class;
 546}
 547
 548typedef struct OCFData
 549{
 550    void (*fn)(ObjectClass *klass, void *opaque);
 551    const char *implements_type;
 552    bool include_abstract;
 553    void *opaque;
 554} OCFData;
 555
 556static void object_class_foreach_tramp(gpointer key, gpointer value,
 557                                       gpointer opaque)
 558{
 559    OCFData *data = opaque;
 560    TypeImpl *type = value;
 561    ObjectClass *k;
 562
 563    type_initialize(type);
 564    k = type->class;
 565
 566    if (!data->include_abstract && type->abstract) {
 567        return;
 568    }
 569
 570    if (data->implements_type && 
 571        !object_class_dynamic_cast(k, data->implements_type)) {
 572        return;
 573    }
 574
 575    data->fn(k, data->opaque);
 576}
 577
 578void object_class_foreach(void (*fn)(ObjectClass *klass, void *opaque),
 579                          const char *implements_type, bool include_abstract,
 580                          void *opaque)
 581{
 582    OCFData data = { fn, implements_type, include_abstract, opaque };
 583
 584    g_hash_table_foreach(type_table_get(), object_class_foreach_tramp, &data);
 585}
 586
 587static void object_class_get_list_tramp(ObjectClass *klass, void *opaque)
 588{
 589    GSList **list = opaque;
 590
 591    *list = g_slist_prepend(*list, klass);
 592}
 593
 594GSList *object_class_get_list(const char *implements_type,
 595                              bool include_abstract)
 596{
 597    GSList *list = NULL;
 598
 599    object_class_foreach(object_class_get_list_tramp,
 600                         implements_type, include_abstract, &list);
 601    return list;
 602}
 603
 604void object_ref(Object *obj)
 605{
 606    obj->ref++;
 607}
 608
 609void object_unref(Object *obj)
 610{
 611    g_assert(obj->ref > 0);
 612    obj->ref--;
 613
 614    /* parent always holds a reference to its children */
 615    if (obj->ref == 0) {
 616        object_finalize(obj);
 617    }
 618}
 619
 620void object_property_add(Object *obj, const char *name, const char *type,
 621                         ObjectPropertyAccessor *get,
 622                         ObjectPropertyAccessor *set,
 623                         ObjectPropertyRelease *release,
 624                         void *opaque, Error **errp)
 625{
 626    ObjectProperty *prop = g_malloc0(sizeof(*prop));
 627
 628    prop->name = g_strdup(name);
 629    prop->type = g_strdup(type);
 630
 631    prop->get = get;
 632    prop->set = set;
 633    prop->release = release;
 634    prop->opaque = opaque;
 635
 636    QTAILQ_INSERT_TAIL(&obj->properties, prop, node);
 637}
 638
 639static ObjectProperty *object_property_find(Object *obj, const char *name)
 640{
 641    ObjectProperty *prop;
 642
 643    QTAILQ_FOREACH(prop, &obj->properties, node) {
 644        if (strcmp(prop->name, name) == 0) {
 645            return prop;
 646        }
 647    }
 648
 649    return NULL;
 650}
 651
 652void object_property_del(Object *obj, const char *name, Error **errp)
 653{
 654    ObjectProperty *prop = object_property_find(obj, name);
 655
 656    QTAILQ_REMOVE(&obj->properties, prop, node);
 657
 658    prop->release(obj, prop->name, prop->opaque);
 659
 660    g_free(prop->name);
 661    g_free(prop->type);
 662    g_free(prop);
 663}
 664
 665void object_property_get(Object *obj, Visitor *v, const char *name,
 666                         Error **errp)
 667{
 668    ObjectProperty *prop = object_property_find(obj, name);
 669
 670    if (prop == NULL) {
 671        error_set(errp, QERR_PROPERTY_NOT_FOUND, "", name);
 672        return;
 673    }
 674
 675    if (!prop->get) {
 676        error_set(errp, QERR_PERMISSION_DENIED);
 677    } else {
 678        prop->get(obj, v, prop->opaque, name, errp);
 679    }
 680}
 681
 682void object_property_set(Object *obj, Visitor *v, const char *name,
 683                         Error **errp)
 684{
 685    ObjectProperty *prop = object_property_find(obj, name);
 686
 687    if (prop == NULL) {
 688        error_set(errp, QERR_PROPERTY_NOT_FOUND, "", name);
 689        return;
 690    }
 691
 692    if (!prop->set) {
 693        error_set(errp, QERR_PERMISSION_DENIED);
 694    } else {
 695        prop->set(obj, v, prop->opaque, name, errp);
 696    }
 697}
 698
 699void object_property_set_str(Object *obj, const char *value,
 700                             const char *name, Error **errp)
 701{
 702    QString *qstr = qstring_from_str(value);
 703    object_property_set_qobject(obj, QOBJECT(qstr), name, errp);
 704
 705    QDECREF(qstr);
 706}
 707
 708char *object_property_get_str(Object *obj, const char *name,
 709                              Error **errp)
 710{
 711    QObject *ret = object_property_get_qobject(obj, name, errp);
 712    QString *qstring;
 713    char *retval;
 714
 715    if (!ret) {
 716        return NULL;
 717    }
 718    qstring = qobject_to_qstring(ret);
 719    if (!qstring) {
 720        error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, "string");
 721        retval = NULL;
 722    } else {
 723        retval = g_strdup(qstring_get_str(qstring));
 724    }
 725
 726    QDECREF(qstring);
 727    return retval;
 728}
 729
 730void object_property_set_link(Object *obj, Object *value,
 731                              const char *name, Error **errp)
 732{
 733    object_property_set_str(obj, object_get_canonical_path(value),
 734                            name, errp);
 735}
 736
 737Object *object_property_get_link(Object *obj, const char *name,
 738                                 Error **errp)
 739{
 740    char *str = object_property_get_str(obj, name, errp);
 741    Object *target = NULL;
 742
 743    if (str && *str) {
 744        target = object_resolve_path(str, NULL);
 745        if (!target) {
 746            error_set(errp, QERR_DEVICE_NOT_FOUND, str);
 747        }
 748    }
 749
 750    g_free(str);
 751    return target;
 752}
 753
 754void object_property_set_bool(Object *obj, bool value,
 755                              const char *name, Error **errp)
 756{
 757    QBool *qbool = qbool_from_int(value);
 758    object_property_set_qobject(obj, QOBJECT(qbool), name, errp);
 759
 760    QDECREF(qbool);
 761}
 762
 763bool object_property_get_bool(Object *obj, const char *name,
 764                              Error **errp)
 765{
 766    QObject *ret = object_property_get_qobject(obj, name, errp);
 767    QBool *qbool;
 768    bool retval;
 769
 770    if (!ret) {
 771        return false;
 772    }
 773    qbool = qobject_to_qbool(ret);
 774    if (!qbool) {
 775        error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, "boolean");
 776        retval = false;
 777    } else {
 778        retval = qbool_get_int(qbool);
 779    }
 780
 781    QDECREF(qbool);
 782    return retval;
 783}
 784
 785void object_property_set_int(Object *obj, int64_t value,
 786                             const char *name, Error **errp)
 787{
 788    QInt *qint = qint_from_int(value);
 789    object_property_set_qobject(obj, QOBJECT(qint), name, errp);
 790
 791    QDECREF(qint);
 792}
 793
 794int64_t object_property_get_int(Object *obj, const char *name,
 795                                Error **errp)
 796{
 797    QObject *ret = object_property_get_qobject(obj, name, errp);
 798    QInt *qint;
 799    int64_t retval;
 800
 801    if (!ret) {
 802        return -1;
 803    }
 804    qint = qobject_to_qint(ret);
 805    if (!qint) {
 806        error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, "int");
 807        retval = -1;
 808    } else {
 809        retval = qint_get_int(qint);
 810    }
 811
 812    QDECREF(qint);
 813    return retval;
 814}
 815
 816void object_property_parse(Object *obj, const char *string,
 817                           const char *name, Error **errp)
 818{
 819    StringInputVisitor *mi;
 820    mi = string_input_visitor_new(string);
 821    object_property_set(obj, string_input_get_visitor(mi), name, errp);
 822
 823    string_input_visitor_cleanup(mi);
 824}
 825
 826char *object_property_print(Object *obj, const char *name,
 827                            Error **errp)
 828{
 829    StringOutputVisitor *mo;
 830    char *string;
 831
 832    mo = string_output_visitor_new();
 833    object_property_get(obj, string_output_get_visitor(mo), name, errp);
 834    string = string_output_get_string(mo);
 835    string_output_visitor_cleanup(mo);
 836    return string;
 837}
 838
 839const char *object_property_get_type(Object *obj, const char *name, Error **errp)
 840{
 841    ObjectProperty *prop = object_property_find(obj, name);
 842
 843    if (prop == NULL) {
 844        error_set(errp, QERR_PROPERTY_NOT_FOUND, "", name);
 845        return NULL;
 846    }
 847
 848    return prop->type;
 849}
 850
 851Object *object_get_root(void)
 852{
 853    static Object *root;
 854
 855    if (!root) {
 856        root = object_new("container");
 857    }
 858
 859    return root;
 860}
 861
 862static void object_get_child_property(Object *obj, Visitor *v, void *opaque,
 863                                      const char *name, Error **errp)
 864{
 865    Object *child = opaque;
 866    gchar *path;
 867
 868    path = object_get_canonical_path(child);
 869    visit_type_str(v, &path, name, errp);
 870    g_free(path);
 871}
 872
 873static void object_finalize_child_property(Object *obj, const char *name,
 874                                           void *opaque)
 875{
 876    Object *child = opaque;
 877
 878    object_unref(child);
 879}
 880
 881void object_property_add_child(Object *obj, const char *name,
 882                               Object *child, Error **errp)
 883{
 884    gchar *type;
 885
 886    /* Registering an interface object in the composition tree will mightily
 887     * confuse object_get_canonical_path (which, on the other hand, knows how
 888     * to get the canonical path of an interface object).
 889     */
 890    assert(!object_is_type(obj, type_interface));
 891
 892    type = g_strdup_printf("child<%s>", object_get_typename(OBJECT(child)));
 893
 894    object_property_add(obj, name, type, object_get_child_property,
 895                        NULL, object_finalize_child_property, child, errp);
 896
 897    object_ref(child);
 898    g_assert(child->parent == NULL);
 899    child->parent = obj;
 900
 901    g_free(type);
 902}
 903
 904static void object_get_link_property(Object *obj, Visitor *v, void *opaque,
 905                                     const char *name, Error **errp)
 906{
 907    Object **child = opaque;
 908    gchar *path;
 909
 910    if (*child) {
 911        path = object_get_canonical_path(*child);
 912        visit_type_str(v, &path, name, errp);
 913        g_free(path);
 914    } else {
 915        path = (gchar *)"";
 916        visit_type_str(v, &path, name, errp);
 917    }
 918}
 919
 920static void object_set_link_property(Object *obj, Visitor *v, void *opaque,
 921                                     const char *name, Error **errp)
 922{
 923    Object **child = opaque;
 924    Object *old_target;
 925    bool ambiguous = false;
 926    const char *type;
 927    char *path;
 928    gchar *target_type;
 929
 930    type = object_property_get_type(obj, name, NULL);
 931
 932    visit_type_str(v, &path, name, errp);
 933
 934    old_target = *child;
 935    *child = NULL;
 936
 937    if (strcmp(path, "") != 0) {
 938        Object *target;
 939
 940        /* Go from link<FOO> to FOO.  */
 941        target_type = g_strndup(&type[5], strlen(type) - 6);
 942        target = object_resolve_path_type(path, target_type, &ambiguous);
 943
 944        if (ambiguous) {
 945            error_set(errp, QERR_AMBIGUOUS_PATH, path);
 946        } else if (target) {
 947            object_ref(target);
 948            *child = target;
 949        } else {
 950            target = object_resolve_path(path, &ambiguous);
 951            if (target || ambiguous) {
 952                error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, target_type);
 953            } else {
 954                error_set(errp, QERR_DEVICE_NOT_FOUND, path);
 955            }
 956        }
 957        g_free(target_type);
 958    }
 959
 960    g_free(path);
 961
 962    if (old_target != NULL) {
 963        object_unref(old_target);
 964    }
 965}
 966
 967void object_property_add_link(Object *obj, const char *name,
 968                              const char *type, Object **child,
 969                              Error **errp)
 970{
 971    gchar *full_type;
 972
 973    full_type = g_strdup_printf("link<%s>", type);
 974
 975    object_property_add(obj, name, full_type,
 976                        object_get_link_property,
 977                        object_set_link_property,
 978                        NULL, child, errp);
 979
 980    g_free(full_type);
 981}
 982
 983gchar *object_get_canonical_path(Object *obj)
 984{
 985    Object *root = object_get_root();
 986    char *newpath = NULL, *path = NULL;
 987
 988    if (object_is_type(obj, type_interface)) {
 989        obj = INTERFACE(obj)->obj;
 990    }
 991
 992    while (obj != root) {
 993        ObjectProperty *prop = NULL;
 994
 995        g_assert(obj->parent != NULL);
 996
 997        QTAILQ_FOREACH(prop, &obj->parent->properties, node) {
 998            if (!strstart(prop->type, "child<", NULL)) {
 999                continue;
1000            }
1001
1002            if (prop->opaque == obj) {
1003                if (path) {
1004                    newpath = g_strdup_printf("%s/%s", prop->name, path);
1005                    g_free(path);
1006                    path = newpath;
1007                } else {
1008                    path = g_strdup(prop->name);
1009                }
1010                break;
1011            }
1012        }
1013
1014        g_assert(prop != NULL);
1015
1016        obj = obj->parent;
1017    }
1018
1019    newpath = g_strdup_printf("/%s", path);
1020    g_free(path);
1021
1022    return newpath;
1023}
1024
1025Object *object_resolve_path_component(Object *parent, gchar *part)
1026{
1027    ObjectProperty *prop = object_property_find(parent, part);
1028    if (prop == NULL) {
1029        return NULL;
1030    }
1031
1032    if (strstart(prop->type, "link<", NULL)) {
1033        return *(Object **)prop->opaque;
1034    } else if (strstart(prop->type, "child<", NULL)) {
1035        return prop->opaque;
1036    } else {
1037        return NULL;
1038    }
1039}
1040
1041static Object *object_resolve_abs_path(Object *parent,
1042                                          gchar **parts,
1043                                          const char *typename,
1044                                          int index)
1045{
1046    Object *child;
1047
1048    if (parts[index] == NULL) {
1049        return object_dynamic_cast(parent, typename);
1050    }
1051
1052    if (strcmp(parts[index], "") == 0) {
1053        return object_resolve_abs_path(parent, parts, typename, index + 1);
1054    }
1055
1056    child = object_resolve_path_component(parent, parts[index]);
1057    if (!child) {
1058        return NULL;
1059    }
1060
1061    return object_resolve_abs_path(child, parts, typename, index + 1);
1062}
1063
1064static Object *object_resolve_partial_path(Object *parent,
1065                                              gchar **parts,
1066                                              const char *typename,
1067                                              bool *ambiguous)
1068{
1069    Object *obj;
1070    ObjectProperty *prop;
1071
1072    obj = object_resolve_abs_path(parent, parts, typename, 0);
1073
1074    QTAILQ_FOREACH(prop, &parent->properties, node) {
1075        Object *found;
1076
1077        if (!strstart(prop->type, "child<", NULL)) {
1078            continue;
1079        }
1080
1081        found = object_resolve_partial_path(prop->opaque, parts,
1082                                            typename, ambiguous);
1083        if (found) {
1084            if (obj) {
1085                if (ambiguous) {
1086                    *ambiguous = true;
1087                }
1088                return NULL;
1089            }
1090            obj = found;
1091        }
1092
1093        if (ambiguous && *ambiguous) {
1094            return NULL;
1095        }
1096    }
1097
1098    return obj;
1099}
1100
1101Object *object_resolve_path_type(const char *path, const char *typename,
1102                                 bool *ambiguous)
1103{
1104    bool partial_path = true;
1105    Object *obj;
1106    gchar **parts;
1107
1108    parts = g_strsplit(path, "/", 0);
1109    if (parts == NULL || parts[0] == NULL) {
1110        g_strfreev(parts);
1111        return object_get_root();
1112    }
1113
1114    if (strcmp(parts[0], "") == 0) {
1115        partial_path = false;
1116    }
1117
1118    if (partial_path) {
1119        if (ambiguous) {
1120            *ambiguous = false;
1121        }
1122        obj = object_resolve_partial_path(object_get_root(), parts,
1123                                          typename, ambiguous);
1124    } else {
1125        obj = object_resolve_abs_path(object_get_root(), parts, typename, 1);
1126    }
1127
1128    g_strfreev(parts);
1129
1130    return obj;
1131}
1132
1133Object *object_resolve_path(const char *path, bool *ambiguous)
1134{
1135    return object_resolve_path_type(path, TYPE_OBJECT, ambiguous);
1136}
1137
1138typedef struct StringProperty
1139{
1140    char *(*get)(Object *, Error **);
1141    void (*set)(Object *, const char *, Error **);
1142} StringProperty;
1143
1144static void property_get_str(Object *obj, Visitor *v, void *opaque,
1145                             const char *name, Error **errp)
1146{
1147    StringProperty *prop = opaque;
1148    char *value;
1149
1150    value = prop->get(obj, errp);
1151    if (value) {
1152        visit_type_str(v, &value, name, errp);
1153        g_free(value);
1154    }
1155}
1156
1157static void property_set_str(Object *obj, Visitor *v, void *opaque,
1158                             const char *name, Error **errp)
1159{
1160    StringProperty *prop = opaque;
1161    char *value;
1162    Error *local_err = NULL;
1163
1164    visit_type_str(v, &value, name, &local_err);
1165    if (local_err) {
1166        error_propagate(errp, local_err);
1167        return;
1168    }
1169
1170    prop->set(obj, value, errp);
1171    g_free(value);
1172}
1173
1174static void property_release_str(Object *obj, const char *name,
1175                                 void *opaque)
1176{
1177    StringProperty *prop = opaque;
1178    g_free(prop);
1179}
1180
1181void object_property_add_str(Object *obj, const char *name,
1182                           char *(*get)(Object *, Error **),
1183                           void (*set)(Object *, const char *, Error **),
1184                           Error **errp)
1185{
1186    StringProperty *prop = g_malloc0(sizeof(*prop));
1187
1188    prop->get = get;
1189    prop->set = set;
1190
1191    object_property_add(obj, name, "string",
1192                        get ? property_get_str : NULL,
1193                        set ? property_set_str : NULL,
1194                        property_release_str,
1195                        prop, errp);
1196}
1197