Statistics
| Branch: | Revision:

root / qom / object.c @ 7b7b7d18

History | View | Annotate | Download (25.1 kB)

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

    
17
/* TODO: replace QObject with a simpler visitor to avoid a dependency
18
 * of the QOM core on QObject?  */
19
#include "qemu/qom-qobject.h"
20
#include "qobject.h"
21
#include "qbool.h"
22
#include "qint.h"
23
#include "qstring.h"
24

    
25
#define MAX_INTERFACES 32
26

    
27
typedef struct InterfaceImpl InterfaceImpl;
28
typedef struct TypeImpl TypeImpl;
29

    
30
struct InterfaceImpl
31
{
32
    const char *parent;
33
    void (*interface_initfn)(ObjectClass *class, void *data);
34
    TypeImpl *type;
35
};
36

    
37
struct TypeImpl
38
{
39
    const char *name;
40

    
41
    size_t class_size;
42

    
43
    size_t instance_size;
44

    
45
    void (*class_init)(ObjectClass *klass, void *data);
46
    void (*class_finalize)(ObjectClass *klass, void *data);
47

    
48
    void *class_data;
49

    
50
    void (*instance_init)(Object *obj);
51
    void (*instance_finalize)(Object *obj);
52

    
53
    bool abstract;
54

    
55
    const char *parent;
56
    TypeImpl *parent_type;
57

    
58
    ObjectClass *class;
59

    
60
    int num_interfaces;
61
    InterfaceImpl interfaces[MAX_INTERFACES];
62
};
63

    
64
typedef struct Interface
65
{
66
    Object parent;
67
    Object *obj;
68
} Interface;
69

    
70
#define INTERFACE(obj) OBJECT_CHECK(Interface, obj, TYPE_INTERFACE)
71

    
72
static Type type_interface;
73

    
74
static GHashTable *type_table_get(void)
75
{
76
    static GHashTable *type_table;
77

    
78
    if (type_table == NULL) {
79
        type_table = g_hash_table_new(g_str_hash, g_str_equal);
80
    }
81

    
82
    return type_table;
83
}
84

    
85
static void type_table_add(TypeImpl *ti)
86
{
87
    g_hash_table_insert(type_table_get(), (void *)ti->name, ti);
88
}
89

    
90
static TypeImpl *type_table_lookup(const char *name)
91
{
92
    return g_hash_table_lookup(type_table_get(), name);
93
}
94

    
95
TypeImpl *type_register(const TypeInfo *info)
96
{
97
    TypeImpl *ti = g_malloc0(sizeof(*ti));
98

    
99
    g_assert(info->name != NULL);
100

    
101
    if (type_table_lookup(info->name) != NULL) {
102
        fprintf(stderr, "Registering `%s' which already exists\n", info->name);
103
        abort();
104
    }
105

    
106
    ti->name = g_strdup(info->name);
107
    ti->parent = g_strdup(info->parent);
108

    
109
    ti->class_size = info->class_size;
110
    ti->instance_size = info->instance_size;
111

    
112
    ti->class_init = info->class_init;
113
    ti->class_finalize = info->class_finalize;
114
    ti->class_data = info->class_data;
115

    
116
    ti->instance_init = info->instance_init;
117
    ti->instance_finalize = info->instance_finalize;
118

    
119
    ti->abstract = info->abstract;
120

    
121
    if (info->interfaces) {
122
        int i;
123

    
124
        for (i = 0; info->interfaces[i].type; i++) {
125
            ti->interfaces[i].parent = info->interfaces[i].type;
126
            ti->interfaces[i].interface_initfn = info->interfaces[i].interface_initfn;
127
            ti->num_interfaces++;
128
        }
129
    }
130

    
131
    type_table_add(ti);
132

    
133
    return ti;
134
}
135

    
136
TypeImpl *type_register_static(const TypeInfo *info)
137
{
138
    return type_register(info);
139
}
140

    
141
static TypeImpl *type_get_by_name(const char *name)
142
{
143
    if (name == NULL) {
144
        return NULL;
145
    }
146

    
147
    return type_table_lookup(name);
148
}
149

    
150
static TypeImpl *type_get_parent(TypeImpl *type)
151
{
152
    if (!type->parent_type && type->parent) {
153
        type->parent_type = type_get_by_name(type->parent);
154
        g_assert(type->parent_type != NULL);
155
    }
156

    
157
    return type->parent_type;
158
}
159

    
160
static bool type_has_parent(TypeImpl *type)
161
{
162
    return (type->parent != NULL);
163
}
164

    
165
static size_t type_class_get_size(TypeImpl *ti)
166
{
167
    if (ti->class_size) {
168
        return ti->class_size;
169
    }
170

    
171
    if (type_has_parent(ti)) {
172
        return type_class_get_size(type_get_parent(ti));
173
    }
174

    
175
    return sizeof(ObjectClass);
176
}
177

    
178
static void type_class_interface_init(TypeImpl *ti, InterfaceImpl *iface)
179
{
180
    TypeInfo info = {
181
        .instance_size = sizeof(Interface),
182
        .parent = iface->parent,
183
        .class_size = sizeof(InterfaceClass),
184
        .class_init = iface->interface_initfn,
185
        .abstract = true,
186
    };
187
    char *name = g_strdup_printf("<%s::%s>", ti->name, iface->parent);
188

    
189
    info.name = name;
190
    iface->type = type_register(&info);
191
    g_free(name);
192
}
193

    
194
static void type_class_init(TypeImpl *ti)
195
{
196
    size_t class_size = sizeof(ObjectClass);
197
    int i;
198

    
199
    if (ti->class) {
200
        return;
201
    }
202

    
203
    ti->class_size = type_class_get_size(ti);
204

    
205
    ti->class = g_malloc0(ti->class_size);
206
    ti->class->type = ti;
207

    
208
    if (type_has_parent(ti)) {
209
        TypeImpl *parent = type_get_parent(ti);
210

    
211
        type_class_init(parent);
212

    
213
        class_size = parent->class_size;
214
        g_assert(parent->class_size <= ti->class_size);
215

    
216
        memcpy((void *)ti->class + sizeof(ObjectClass),
217
               (void *)parent->class + sizeof(ObjectClass),
218
               parent->class_size - sizeof(ObjectClass));
219
    }
220

    
221
    memset((void *)ti->class + class_size, 0, ti->class_size - class_size);
222

    
223
    for (i = 0; i < ti->num_interfaces; i++) {
224
        type_class_interface_init(ti, &ti->interfaces[i]);
225
    }
226

    
227
    if (ti->class_init) {
228
        ti->class_init(ti->class, ti->class_data);
229
    }
230
}
231

    
232
static void object_interface_init(Object *obj, InterfaceImpl *iface)
233
{
234
    TypeImpl *ti = iface->type;
235
    Interface *iface_obj;
236

    
237
    iface_obj = INTERFACE(object_new(ti->name));
238
    iface_obj->obj = obj;
239

    
240
    obj->interfaces = g_slist_prepend(obj->interfaces, iface_obj);
241
}
242

    
243
static void object_init_with_type(Object *obj, TypeImpl *ti)
244
{
245
    int i;
246

    
247
    if (type_has_parent(ti)) {
248
        object_init_with_type(obj, type_get_parent(ti));
249
    }
250

    
251
    for (i = 0; i < ti->num_interfaces; i++) {
252
        object_interface_init(obj, &ti->interfaces[i]);
253
    }
254

    
255
    if (ti->instance_init) {
256
        ti->instance_init(obj);
257
    }
258
}
259

    
260
void object_initialize_with_type(void *data, TypeImpl *type)
261
{
262
    Object *obj = data;
263

    
264
    g_assert(type != NULL);
265
    g_assert(type->instance_size >= sizeof(ObjectClass));
266

    
267
    type_class_init(type);
268
    g_assert(type->abstract == false);
269

    
270
    memset(obj, 0, type->instance_size);
271
    obj->class = type->class;
272
    QTAILQ_INIT(&obj->properties);
273
    object_init_with_type(obj, type);
274
}
275

    
276
void object_initialize(void *data, const char *typename)
277
{
278
    TypeImpl *type = type_get_by_name(typename);
279

    
280
    object_initialize_with_type(data, type);
281
}
282

    
283
static void object_property_del_all(Object *obj)
284
{
285
    while (!QTAILQ_EMPTY(&obj->properties)) {
286
        ObjectProperty *prop = QTAILQ_FIRST(&obj->properties);
287

    
288
        QTAILQ_REMOVE(&obj->properties, prop, node);
289

    
290
        if (prop->release) {
291
            prop->release(obj, prop->name, prop->opaque);
292
        }
293

    
294
        g_free(prop->name);
295
        g_free(prop->type);
296
        g_free(prop);
297
    }
298
}
299

    
300
static void object_property_del_child(Object *obj, Object *child, Error **errp)
301
{
302
    ObjectProperty *prop;
303

    
304
    QTAILQ_FOREACH(prop, &obj->properties, node) {
305
        if (!strstart(prop->type, "child<", NULL)) {
306
            continue;
307
        }
308

    
309
        if (prop->opaque == child) {
310
            object_property_del(obj, prop->name, errp);
311
        }
312
    }
313
}
314

    
315
void object_unparent(Object *obj)
316
{
317
    if (obj->parent) {
318
        object_property_del_child(obj->parent, obj, NULL);
319
    }
320
}
321

    
322
static void object_deinit(Object *obj, TypeImpl *type)
323
{
324
    if (type->instance_finalize) {
325
        type->instance_finalize(obj);
326
    }
327

    
328
    while (obj->interfaces) {
329
        Interface *iface_obj = obj->interfaces->data;
330
        obj->interfaces = g_slist_delete_link(obj->interfaces, obj->interfaces);
331
        object_delete(OBJECT(iface_obj));
332
    }
333

    
334
    if (type_has_parent(type)) {
335
        object_deinit(obj, type_get_parent(type));
336
    }
337

    
338
    object_unparent(obj);
339
}
340

    
341
void object_finalize(void *data)
342
{
343
    Object *obj = data;
344
    TypeImpl *ti = obj->class->type;
345

    
346
    object_deinit(obj, ti);
347
    object_property_del_all(obj);
348

    
349
    g_assert(obj->ref == 0);
350
}
351

    
352
Object *object_new_with_type(Type type)
353
{
354
    Object *obj;
355

    
356
    g_assert(type != NULL);
357

    
358
    obj = g_malloc(type->instance_size);
359
    object_initialize_with_type(obj, type);
360
    object_ref(obj);
361

    
362
    return obj;
363
}
364

    
365
Object *object_new(const char *typename)
366
{
367
    TypeImpl *ti = type_get_by_name(typename);
368

    
369
    return object_new_with_type(ti);
370
}
371

    
372
void object_delete(Object *obj)
373
{
374
    object_unref(obj);
375
    g_assert(obj->ref == 0);
376
    g_free(obj);
377
}
378

    
379
static bool type_is_ancestor(TypeImpl *type, TypeImpl *target_type)
380
{
381
    assert(target_type);
382

    
383
    /* Check if typename is a direct ancestor of type */
384
    while (type) {
385
        if (type == target_type) {
386
            return true;
387
        }
388

    
389
        type = type_get_parent(type);
390
    }
391

    
392
    return false;
393
}
394

    
395
static bool object_is_type(Object *obj, TypeImpl *target_type)
396
{
397
    return !target_type || type_is_ancestor(obj->class->type, target_type);
398
}
399

    
400
Object *object_dynamic_cast(Object *obj, const char *typename)
401
{
402
    TypeImpl *target_type = type_get_by_name(typename);
403
    GSList *i;
404

    
405
    /* Check if typename is a direct ancestor.  Special-case TYPE_OBJECT,
406
     * we want to go back from interfaces to the parent.
407
    */
408
    if (target_type && object_is_type(obj, target_type)) {
409
        return obj;
410
    }
411

    
412
    /* Check if obj is an interface and its containing object is a direct
413
     * ancestor of typename.  In principle we could do this test at the very
414
     * beginning of object_dynamic_cast, avoiding a second call to
415
     * object_is_type.  However, casting between interfaces is relatively
416
     * rare, and object_is_type(obj, type_interface) would fail almost always.
417
     *
418
     * Perhaps we could add a magic value to the object header for increased
419
     * (run-time) type safety and to speed up tests like this one.  If we ever
420
     * do that we can revisit the order here.
421
     */
422
    if (object_is_type(obj, type_interface)) {
423
        assert(!obj->interfaces);
424
        obj = INTERFACE(obj)->obj;
425
        if (object_is_type(obj, target_type)) {
426
            return obj;
427
        }
428
    }
429

    
430
    if (!target_type) {
431
        return obj;
432
    }
433

    
434
    /* Check if obj has an interface of typename */
435
    for (i = obj->interfaces; i; i = i->next) {
436
        Interface *iface = i->data;
437

    
438
        if (object_is_type(OBJECT(iface), target_type)) {
439
            return OBJECT(iface);
440
        }
441
    }
442

    
443
    return NULL;
444
}
445

    
446

    
447
static void register_interface(void)
448
{
449
    static TypeInfo interface_info = {
450
        .name = TYPE_INTERFACE,
451
        .instance_size = sizeof(Interface),
452
        .abstract = true,
453
    };
454

    
455
    type_interface = type_register_static(&interface_info);
456
}
457

    
458
device_init(register_interface);
459

    
460
Object *object_dynamic_cast_assert(Object *obj, const char *typename)
461
{
462
    Object *inst;
463

    
464
    inst = object_dynamic_cast(obj, typename);
465

    
466
    if (!inst) {
467
        fprintf(stderr, "Object %p is not an instance of type %s\n",
468
                obj, typename);
469
        abort();
470
    }
471

    
472
    return inst;
473
}
474

    
475
ObjectClass *object_class_dynamic_cast(ObjectClass *class,
476
                                       const char *typename)
477
{
478
    TypeImpl *target_type = type_get_by_name(typename);
479
    TypeImpl *type = class->type;
480

    
481
    while (type) {
482
        if (type == target_type) {
483
            return class;
484
        }
485

    
486
        type = type_get_parent(type);
487
    }
488

    
489
    return NULL;
490
}
491

    
492
ObjectClass *object_class_dynamic_cast_assert(ObjectClass *class,
493
                                              const char *typename)
494
{
495
    ObjectClass *ret = object_class_dynamic_cast(class, typename);
496

    
497
    if (!ret) {
498
        fprintf(stderr, "Object %p is not an instance of type %s\n",
499
                class, typename);
500
        abort();
501
    }
502

    
503
    return ret;
504
}
505

    
506
const char *object_get_typename(Object *obj)
507
{
508
    return obj->class->type->name;
509
}
510

    
511
ObjectClass *object_get_class(Object *obj)
512
{
513
    return obj->class;
514
}
515

    
516
const char *object_class_get_name(ObjectClass *klass)
517
{
518
    return klass->type->name;
519
}
520

    
521
ObjectClass *object_class_by_name(const char *typename)
522
{
523
    TypeImpl *type = type_get_by_name(typename);
524

    
525
    if (!type) {
526
        return NULL;
527
    }
528

    
529
    type_class_init(type);
530

    
531
    return type->class;
532
}
533

    
534
typedef struct OCFData
535
{
536
    void (*fn)(ObjectClass *klass, void *opaque);
537
    const char *implements_type;
538
    bool include_abstract;
539
    void *opaque;
540
} OCFData;
541

    
542
static void object_class_foreach_tramp(gpointer key, gpointer value,
543
                                       gpointer opaque)
544
{
545
    OCFData *data = opaque;
546
    TypeImpl *type = value;
547
    ObjectClass *k;
548

    
549
    type_class_init(type);
550
    k = type->class;
551

    
552
    if (!data->include_abstract && type->abstract) {
553
        return;
554
    }
555

    
556
    if (data->implements_type && 
557
        !object_class_dynamic_cast(k, data->implements_type)) {
558
        return;
559
    }
560

    
561
    data->fn(k, data->opaque);
562
}
563

    
564
void object_class_foreach(void (*fn)(ObjectClass *klass, void *opaque),
565
                          const char *implements_type, bool include_abstract,
566
                          void *opaque)
567
{
568
    OCFData data = { fn, implements_type, include_abstract, opaque };
569

    
570
    g_hash_table_foreach(type_table_get(), object_class_foreach_tramp, &data);
571
}
572

    
573
void object_ref(Object *obj)
574
{
575
    obj->ref++;
576
}
577

    
578
void object_unref(Object *obj)
579
{
580
    g_assert(obj->ref > 0);
581
    obj->ref--;
582

    
583
    /* parent always holds a reference to its children */
584
    if (obj->ref == 0) {
585
        object_finalize(obj);
586
    }
587
}
588

    
589
void object_property_add(Object *obj, const char *name, const char *type,
590
                         ObjectPropertyAccessor *get,
591
                         ObjectPropertyAccessor *set,
592
                         ObjectPropertyRelease *release,
593
                         void *opaque, Error **errp)
594
{
595
    ObjectProperty *prop = g_malloc0(sizeof(*prop));
596

    
597
    prop->name = g_strdup(name);
598
    prop->type = g_strdup(type);
599

    
600
    prop->get = get;
601
    prop->set = set;
602
    prop->release = release;
603
    prop->opaque = opaque;
604

    
605
    QTAILQ_INSERT_TAIL(&obj->properties, prop, node);
606
}
607

    
608
static ObjectProperty *object_property_find(Object *obj, const char *name)
609
{
610
    ObjectProperty *prop;
611

    
612
    QTAILQ_FOREACH(prop, &obj->properties, node) {
613
        if (strcmp(prop->name, name) == 0) {
614
            return prop;
615
        }
616
    }
617

    
618
    return NULL;
619
}
620

    
621
void object_property_del(Object *obj, const char *name, Error **errp)
622
{
623
    ObjectProperty *prop = object_property_find(obj, name);
624

    
625
    QTAILQ_REMOVE(&obj->properties, prop, node);
626

    
627
    prop->release(obj, prop->name, prop->opaque);
628

    
629
    g_free(prop->name);
630
    g_free(prop->type);
631
    g_free(prop);
632
}
633

    
634
void object_property_get(Object *obj, Visitor *v, const char *name,
635
                         Error **errp)
636
{
637
    ObjectProperty *prop = object_property_find(obj, name);
638

    
639
    if (prop == NULL) {
640
        error_set(errp, QERR_PROPERTY_NOT_FOUND, "", name);
641
        return;
642
    }
643

    
644
    if (!prop->get) {
645
        error_set(errp, QERR_PERMISSION_DENIED);
646
    } else {
647
        prop->get(obj, v, prop->opaque, name, errp);
648
    }
649
}
650

    
651
void object_property_set(Object *obj, Visitor *v, const char *name,
652
                         Error **errp)
653
{
654
    ObjectProperty *prop = object_property_find(obj, name);
655

    
656
    if (prop == NULL) {
657
        error_set(errp, QERR_PROPERTY_NOT_FOUND, "", name);
658
        return;
659
    }
660

    
661
    if (!prop->set) {
662
        error_set(errp, QERR_PERMISSION_DENIED);
663
    } else {
664
        prop->set(obj, v, prop->opaque, name, errp);
665
    }
666
}
667

    
668
void object_property_set_str(Object *obj, const char *value,
669
                             const char *name, Error **errp)
670
{
671
    QString *qstr = qstring_from_str(value);
672
    object_property_set_qobject(obj, QOBJECT(qstr), name, errp);
673

    
674
    QDECREF(qstr);
675
}
676

    
677
char *object_property_get_str(Object *obj, const char *name,
678
                              Error **errp)
679
{
680
    QObject *ret = object_property_get_qobject(obj, name, errp);
681
    QString *qstring;
682
    char *retval;
683

    
684
    if (!ret) {
685
        return NULL;
686
    }
687
    qstring = qobject_to_qstring(ret);
688
    if (!qstring) {
689
        error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, "string");
690
        retval = NULL;
691
    } else {
692
        retval = g_strdup(qstring_get_str(qstring));
693
    }
694

    
695
    QDECREF(qstring);
696
    return retval;
697
}
698

    
699
void object_property_set_bool(Object *obj, bool value,
700
                              const char *name, Error **errp)
701
{
702
    QBool *qbool = qbool_from_int(value);
703
    object_property_set_qobject(obj, QOBJECT(qbool), name, errp);
704

    
705
    QDECREF(qbool);
706
}
707

    
708
bool object_property_get_bool(Object *obj, const char *name,
709
                              Error **errp)
710
{
711
    QObject *ret = object_property_get_qobject(obj, name, errp);
712
    QBool *qbool;
713
    bool retval;
714

    
715
    if (!ret) {
716
        return false;
717
    }
718
    qbool = qobject_to_qbool(ret);
719
    if (!qbool) {
720
        error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, "boolean");
721
        retval = false;
722
    } else {
723
        retval = qbool_get_int(qbool);
724
    }
725

    
726
    QDECREF(qbool);
727
    return retval;
728
}
729

    
730
void object_property_set_int(Object *obj, int64_t value,
731
                             const char *name, Error **errp)
732
{
733
    QInt *qint = qint_from_int(value);
734
    object_property_set_qobject(obj, QOBJECT(qint), name, errp);
735

    
736
    QDECREF(qint);
737
}
738

    
739
int64_t object_property_get_int(Object *obj, const char *name,
740
                                Error **errp)
741
{
742
    QObject *ret = object_property_get_qobject(obj, name, errp);
743
    QInt *qint;
744
    int64_t retval;
745

    
746
    if (!ret) {
747
        return -1;
748
    }
749
    qint = qobject_to_qint(ret);
750
    if (!qint) {
751
        error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, "int");
752
        retval = -1;
753
    } else {
754
        retval = qint_get_int(qint);
755
    }
756

    
757
    QDECREF(qint);
758
    return retval;
759
}
760

    
761
const char *object_property_get_type(Object *obj, const char *name, Error **errp)
762
{
763
    ObjectProperty *prop = object_property_find(obj, name);
764

    
765
    if (prop == NULL) {
766
        error_set(errp, QERR_PROPERTY_NOT_FOUND, "", name);
767
        return NULL;
768
    }
769

    
770
    return prop->type;
771
}
772

    
773
Object *object_get_root(void)
774
{
775
    static Object *root;
776

    
777
    if (!root) {
778
        root = object_new("container");
779
    }
780

    
781
    return root;
782
}
783

    
784
static void object_get_child_property(Object *obj, Visitor *v, void *opaque,
785
                                      const char *name, Error **errp)
786
{
787
    Object *child = opaque;
788
    gchar *path;
789

    
790
    path = object_get_canonical_path(child);
791
    visit_type_str(v, &path, name, errp);
792
    g_free(path);
793
}
794

    
795
static void object_finalize_child_property(Object *obj, const char *name,
796
                                           void *opaque)
797
{
798
    Object *child = opaque;
799

    
800
    object_unref(child);
801
}
802

    
803
void object_property_add_child(Object *obj, const char *name,
804
                               Object *child, Error **errp)
805
{
806
    gchar *type;
807

    
808
    type = g_strdup_printf("child<%s>", object_get_typename(OBJECT(child)));
809

    
810
    object_property_add(obj, name, type, object_get_child_property,
811
                        NULL, object_finalize_child_property, child, errp);
812

    
813
    object_ref(child);
814
    g_assert(child->parent == NULL);
815
    child->parent = obj;
816

    
817
    g_free(type);
818
}
819

    
820
static void object_get_link_property(Object *obj, Visitor *v, void *opaque,
821
                                     const char *name, Error **errp)
822
{
823
    Object **child = opaque;
824
    gchar *path;
825

    
826
    if (*child) {
827
        path = object_get_canonical_path(*child);
828
        visit_type_str(v, &path, name, errp);
829
        g_free(path);
830
    } else {
831
        path = (gchar *)"";
832
        visit_type_str(v, &path, name, errp);
833
    }
834
}
835

    
836
static void object_set_link_property(Object *obj, Visitor *v, void *opaque,
837
                                     const char *name, Error **errp)
838
{
839
    Object **child = opaque;
840
    bool ambiguous = false;
841
    const char *type;
842
    char *path;
843

    
844
    type = object_property_get_type(obj, name, NULL);
845

    
846
    visit_type_str(v, &path, name, errp);
847

    
848
    if (*child) {
849
        object_unref(*child);
850
    }
851

    
852
    if (strcmp(path, "") != 0) {
853
        Object *target;
854

    
855
        target = object_resolve_path(path, &ambiguous);
856
        if (target) {
857
            gchar *target_type;
858

    
859
            target_type = g_strdup(&type[5]);
860
            target_type[strlen(target_type) - 2] = 0;
861

    
862
            if (object_dynamic_cast(target, target_type)) {
863
                object_ref(target);
864
                *child = target;
865
            } else {
866
                error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, type);
867
            }
868

    
869
            g_free(target_type);
870
        } else {
871
            error_set(errp, QERR_DEVICE_NOT_FOUND, path);
872
        }
873
    } else {
874
        *child = NULL;
875
    }
876

    
877
    g_free(path);
878
}
879

    
880
void object_property_add_link(Object *obj, const char *name,
881
                              const char *type, Object **child,
882
                              Error **errp)
883
{
884
    gchar *full_type;
885

    
886
    full_type = g_strdup_printf("link<%s>", type);
887

    
888
    object_property_add(obj, name, full_type,
889
                        object_get_link_property,
890
                        object_set_link_property,
891
                        NULL, child, errp);
892

    
893
    g_free(full_type);
894
}
895

    
896
gchar *object_get_canonical_path(Object *obj)
897
{
898
    Object *root = object_get_root();
899
    char *newpath = NULL, *path = NULL;
900

    
901
    while (obj != root) {
902
        ObjectProperty *prop = NULL;
903

    
904
        g_assert(obj->parent != NULL);
905

    
906
        QTAILQ_FOREACH(prop, &obj->parent->properties, node) {
907
            if (!strstart(prop->type, "child<", NULL)) {
908
                continue;
909
            }
910

    
911
            if (prop->opaque == obj) {
912
                if (path) {
913
                    newpath = g_strdup_printf("%s/%s", prop->name, path);
914
                    g_free(path);
915
                    path = newpath;
916
                } else {
917
                    path = g_strdup(prop->name);
918
                }
919
                break;
920
            }
921
        }
922

    
923
        g_assert(prop != NULL);
924

    
925
        obj = obj->parent;
926
    }
927

    
928
    newpath = g_strdup_printf("/%s", path);
929
    g_free(path);
930

    
931
    return newpath;
932
}
933

    
934
static Object *object_resolve_abs_path(Object *parent,
935
                                          gchar **parts,
936
                                          int index)
937
{
938
    ObjectProperty *prop;
939
    Object *child;
940

    
941
    if (parts[index] == NULL) {
942
        return parent;
943
    }
944

    
945
    if (strcmp(parts[index], "") == 0) {
946
        return object_resolve_abs_path(parent, parts, index + 1);
947
    }
948

    
949
    prop = object_property_find(parent, parts[index]);
950
    if (prop == NULL) {
951
        return NULL;
952
    }
953

    
954
    child = NULL;
955
    if (strstart(prop->type, "link<", NULL)) {
956
        Object **pchild = prop->opaque;
957
        if (*pchild) {
958
            child = *pchild;
959
        }
960
    } else if (strstart(prop->type, "child<", NULL)) {
961
        child = prop->opaque;
962
    }
963

    
964
    if (!child) {
965
        return NULL;
966
    }
967

    
968
    return object_resolve_abs_path(child, parts, index + 1);
969
}
970

    
971
static Object *object_resolve_partial_path(Object *parent,
972
                                              gchar **parts,
973
                                              bool *ambiguous)
974
{
975
    Object *obj;
976
    ObjectProperty *prop;
977

    
978
    obj = object_resolve_abs_path(parent, parts, 0);
979

    
980
    QTAILQ_FOREACH(prop, &parent->properties, node) {
981
        Object *found;
982

    
983
        if (!strstart(prop->type, "child<", NULL)) {
984
            continue;
985
        }
986

    
987
        found = object_resolve_partial_path(prop->opaque, parts, ambiguous);
988
        if (found) {
989
            if (obj) {
990
                if (ambiguous) {
991
                    *ambiguous = true;
992
                }
993
                return NULL;
994
            }
995
            obj = found;
996
        }
997

    
998
        if (ambiguous && *ambiguous) {
999
            return NULL;
1000
        }
1001
    }
1002

    
1003
    return obj;
1004
}
1005

    
1006
Object *object_resolve_path(const char *path, bool *ambiguous)
1007
{
1008
    bool partial_path = true;
1009
    Object *obj;
1010
    gchar **parts;
1011

    
1012
    parts = g_strsplit(path, "/", 0);
1013
    if (parts == NULL || parts[0] == NULL) {
1014
        g_strfreev(parts);
1015
        return object_get_root();
1016
    }
1017

    
1018
    if (strcmp(parts[0], "") == 0) {
1019
        partial_path = false;
1020
    }
1021

    
1022
    if (partial_path) {
1023
        if (ambiguous) {
1024
            *ambiguous = false;
1025
        }
1026
        obj = object_resolve_partial_path(object_get_root(), parts, ambiguous);
1027
    } else {
1028
        obj = object_resolve_abs_path(object_get_root(), parts, 1);
1029
    }
1030

    
1031
    g_strfreev(parts);
1032

    
1033
    return obj;
1034
}
1035

    
1036
typedef struct StringProperty
1037
{
1038
    char *(*get)(Object *, Error **);
1039
    void (*set)(Object *, const char *, Error **);
1040
} StringProperty;
1041

    
1042
static void property_get_str(Object *obj, Visitor *v, void *opaque,
1043
                             const char *name, Error **errp)
1044
{
1045
    StringProperty *prop = opaque;
1046
    char *value;
1047

    
1048
    value = prop->get(obj, errp);
1049
    if (value) {
1050
        visit_type_str(v, &value, name, errp);
1051
        g_free(value);
1052
    }
1053
}
1054

    
1055
static void property_set_str(Object *obj, Visitor *v, void *opaque,
1056
                             const char *name, Error **errp)
1057
{
1058
    StringProperty *prop = opaque;
1059
    char *value;
1060
    Error *local_err = NULL;
1061

    
1062
    visit_type_str(v, &value, name, &local_err);
1063
    if (local_err) {
1064
        error_propagate(errp, local_err);
1065
        return;
1066
    }
1067

    
1068
    prop->set(obj, value, errp);
1069
    g_free(value);
1070
}
1071

    
1072
static void property_release_str(Object *obj, const char *name,
1073
                                 void *opaque)
1074
{
1075
    StringProperty *prop = opaque;
1076
    g_free(prop);
1077
}
1078

    
1079
void object_property_add_str(Object *obj, const char *name,
1080
                           char *(*get)(Object *, Error **),
1081
                           void (*set)(Object *, const char *, Error **),
1082
                           Error **errp)
1083
{
1084
    StringProperty *prop = g_malloc0(sizeof(*prop));
1085

    
1086
    prop->get = get;
1087
    prop->set = set;
1088

    
1089
    object_property_add(obj, name, "string",
1090
                        get ? property_get_str : NULL,
1091
                        set ? property_set_str : NULL,
1092
                        property_release_str,
1093
                        prop, errp);
1094
}