Statistics
| Branch: | Revision:

root / qom / object.c @ aca59af6

History | View | Annotate | Download (27.8 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
#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

    
29
typedef struct InterfaceImpl InterfaceImpl;
30
typedef struct TypeImpl TypeImpl;
31

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

    
39
struct 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

    
66
typedef struct Interface
67
{
68
    Object parent;
69
    Object *obj;
70
} Interface;
71

    
72
#define INTERFACE(obj) OBJECT_CHECK(Interface, obj, TYPE_INTERFACE)
73

    
74
static Type type_interface;
75

    
76
static 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

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

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

    
97
TypeImpl *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

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

    
143
static 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

    
152
static 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

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

    
167
static 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

    
180
static 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

    
193
static 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

    
209
static void type_class_init(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_class_init(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

    
248
static 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

    
259
static 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

    
276
void object_initialize_with_type(void *data, TypeImpl *type)
277
{
278
    Object *obj = data;
279

    
280
    g_assert(type != NULL);
281
    type_class_init(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

    
292
void 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

    
299
static 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

    
316
static 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

    
328
void object_unparent(Object *obj)
329
{
330
    if (obj->parent) {
331
        object_property_del_child(obj->parent, obj, NULL);
332
    }
333
}
334

    
335
static 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

    
354
void 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

    
365
Object *object_new_with_type(Type type)
366
{
367
    Object *obj;
368

    
369
    g_assert(type != NULL);
370
    type_class_init(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

    
379
Object *object_new(const char *typename)
380
{
381
    TypeImpl *ti = type_get_by_name(typename);
382

    
383
    return object_new_with_type(ti);
384
}
385

    
386
void object_delete(Object *obj)
387
{
388
    object_unref(obj);
389
    g_assert(obj->ref == 0);
390
    g_free(obj);
391
}
392

    
393
static 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

    
409
static bool object_is_type(Object *obj, TypeImpl *target_type)
410
{
411
    return !target_type || type_is_ancestor(obj->class->type, target_type);
412
}
413

    
414
Object *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

    
461
static 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

    
472
type_init(register_types)
473

    
474
Object *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

    
489
ObjectClass *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

    
506
ObjectClass *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

    
520
const char *object_get_typename(Object *obj)
521
{
522
    return obj->class->type->name;
523
}
524

    
525
ObjectClass *object_get_class(Object *obj)
526
{
527
    return obj->class;
528
}
529

    
530
const char *object_class_get_name(ObjectClass *klass)
531
{
532
    return klass->type->name;
533
}
534

    
535
ObjectClass *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_class_init(type);
544

    
545
    return type->class;
546
}
547

    
548
typedef 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

    
556
static 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_class_init(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

    
578
void 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

    
587
void object_ref(Object *obj)
588
{
589
    obj->ref++;
590
}
591

    
592
void object_unref(Object *obj)
593
{
594
    g_assert(obj->ref > 0);
595
    obj->ref--;
596

    
597
    /* parent always holds a reference to its children */
598
    if (obj->ref == 0) {
599
        object_finalize(obj);
600
    }
601
}
602

    
603
void object_property_add(Object *obj, const char *name, const char *type,
604
                         ObjectPropertyAccessor *get,
605
                         ObjectPropertyAccessor *set,
606
                         ObjectPropertyRelease *release,
607
                         void *opaque, Error **errp)
608
{
609
    ObjectProperty *prop = g_malloc0(sizeof(*prop));
610

    
611
    prop->name = g_strdup(name);
612
    prop->type = g_strdup(type);
613

    
614
    prop->get = get;
615
    prop->set = set;
616
    prop->release = release;
617
    prop->opaque = opaque;
618

    
619
    QTAILQ_INSERT_TAIL(&obj->properties, prop, node);
620
}
621

    
622
static ObjectProperty *object_property_find(Object *obj, const char *name)
623
{
624
    ObjectProperty *prop;
625

    
626
    QTAILQ_FOREACH(prop, &obj->properties, node) {
627
        if (strcmp(prop->name, name) == 0) {
628
            return prop;
629
        }
630
    }
631

    
632
    return NULL;
633
}
634

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

    
639
    QTAILQ_REMOVE(&obj->properties, prop, node);
640

    
641
    prop->release(obj, prop->name, prop->opaque);
642

    
643
    g_free(prop->name);
644
    g_free(prop->type);
645
    g_free(prop);
646
}
647

    
648
void object_property_get(Object *obj, Visitor *v, const char *name,
649
                         Error **errp)
650
{
651
    ObjectProperty *prop = object_property_find(obj, name);
652

    
653
    if (prop == NULL) {
654
        error_set(errp, QERR_PROPERTY_NOT_FOUND, "", name);
655
        return;
656
    }
657

    
658
    if (!prop->get) {
659
        error_set(errp, QERR_PERMISSION_DENIED);
660
    } else {
661
        prop->get(obj, v, prop->opaque, name, errp);
662
    }
663
}
664

    
665
void object_property_set(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->set) {
676
        error_set(errp, QERR_PERMISSION_DENIED);
677
    } else {
678
        prop->set(obj, v, prop->opaque, name, errp);
679
    }
680
}
681

    
682
void object_property_set_str(Object *obj, const char *value,
683
                             const char *name, Error **errp)
684
{
685
    QString *qstr = qstring_from_str(value);
686
    object_property_set_qobject(obj, QOBJECT(qstr), name, errp);
687

    
688
    QDECREF(qstr);
689
}
690

    
691
char *object_property_get_str(Object *obj, const char *name,
692
                              Error **errp)
693
{
694
    QObject *ret = object_property_get_qobject(obj, name, errp);
695
    QString *qstring;
696
    char *retval;
697

    
698
    if (!ret) {
699
        return NULL;
700
    }
701
    qstring = qobject_to_qstring(ret);
702
    if (!qstring) {
703
        error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, "string");
704
        retval = NULL;
705
    } else {
706
        retval = g_strdup(qstring_get_str(qstring));
707
    }
708

    
709
    QDECREF(qstring);
710
    return retval;
711
}
712

    
713
void object_property_set_link(Object *obj, Object *value,
714
                              const char *name, Error **errp)
715
{
716
    object_property_set_str(obj, object_get_canonical_path(value),
717
                            name, errp);
718
}
719

    
720
Object *object_property_get_link(Object *obj, const char *name,
721
                                 Error **errp)
722
{
723
    char *str = object_property_get_str(obj, name, errp);
724
    Object *target = NULL;
725

    
726
    if (str && *str) {
727
        target = object_resolve_path(str, NULL);
728
        if (!target) {
729
            error_set(errp, QERR_DEVICE_NOT_FOUND, str);
730
        }
731
    }
732

    
733
    g_free(str);
734
    return target;
735
}
736

    
737
void object_property_set_bool(Object *obj, bool value,
738
                              const char *name, Error **errp)
739
{
740
    QBool *qbool = qbool_from_int(value);
741
    object_property_set_qobject(obj, QOBJECT(qbool), name, errp);
742

    
743
    QDECREF(qbool);
744
}
745

    
746
bool object_property_get_bool(Object *obj, const char *name,
747
                              Error **errp)
748
{
749
    QObject *ret = object_property_get_qobject(obj, name, errp);
750
    QBool *qbool;
751
    bool retval;
752

    
753
    if (!ret) {
754
        return false;
755
    }
756
    qbool = qobject_to_qbool(ret);
757
    if (!qbool) {
758
        error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, "boolean");
759
        retval = false;
760
    } else {
761
        retval = qbool_get_int(qbool);
762
    }
763

    
764
    QDECREF(qbool);
765
    return retval;
766
}
767

    
768
void object_property_set_int(Object *obj, int64_t value,
769
                             const char *name, Error **errp)
770
{
771
    QInt *qint = qint_from_int(value);
772
    object_property_set_qobject(obj, QOBJECT(qint), name, errp);
773

    
774
    QDECREF(qint);
775
}
776

    
777
int64_t object_property_get_int(Object *obj, const char *name,
778
                                Error **errp)
779
{
780
    QObject *ret = object_property_get_qobject(obj, name, errp);
781
    QInt *qint;
782
    int64_t retval;
783

    
784
    if (!ret) {
785
        return -1;
786
    }
787
    qint = qobject_to_qint(ret);
788
    if (!qint) {
789
        error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, "int");
790
        retval = -1;
791
    } else {
792
        retval = qint_get_int(qint);
793
    }
794

    
795
    QDECREF(qint);
796
    return retval;
797
}
798

    
799
void object_property_parse(Object *obj, const char *string,
800
                           const char *name, Error **errp)
801
{
802
    StringInputVisitor *mi;
803
    mi = string_input_visitor_new(string);
804
    object_property_set(obj, string_input_get_visitor(mi), name, errp);
805

    
806
    string_input_visitor_cleanup(mi);
807
}
808

    
809
char *object_property_print(Object *obj, const char *name,
810
                            Error **errp)
811
{
812
    StringOutputVisitor *mo;
813
    char *string;
814

    
815
    mo = string_output_visitor_new();
816
    object_property_get(obj, string_output_get_visitor(mo), name, NULL);
817
    string = string_output_get_string(mo);
818
    string_output_visitor_cleanup(mo);
819
    return string;
820
}
821

    
822
const char *object_property_get_type(Object *obj, const char *name, Error **errp)
823
{
824
    ObjectProperty *prop = object_property_find(obj, name);
825

    
826
    if (prop == NULL) {
827
        error_set(errp, QERR_PROPERTY_NOT_FOUND, "", name);
828
        return NULL;
829
    }
830

    
831
    return prop->type;
832
}
833

    
834
Object *object_get_root(void)
835
{
836
    static Object *root;
837

    
838
    if (!root) {
839
        root = object_new("container");
840
    }
841

    
842
    return root;
843
}
844

    
845
static void object_get_child_property(Object *obj, Visitor *v, void *opaque,
846
                                      const char *name, Error **errp)
847
{
848
    Object *child = opaque;
849
    gchar *path;
850

    
851
    path = object_get_canonical_path(child);
852
    visit_type_str(v, &path, name, errp);
853
    g_free(path);
854
}
855

    
856
static void object_finalize_child_property(Object *obj, const char *name,
857
                                           void *opaque)
858
{
859
    Object *child = opaque;
860

    
861
    object_unref(child);
862
}
863

    
864
void object_property_add_child(Object *obj, const char *name,
865
                               Object *child, Error **errp)
866
{
867
    gchar *type;
868

    
869
    /* Registering an interface object in the composition tree will mightily
870
     * confuse object_get_canonical_path (which, on the other hand, knows how
871
     * to get the canonical path of an interface object).
872
     */
873
    assert(!object_is_type(obj, type_interface));
874

    
875
    type = g_strdup_printf("child<%s>", object_get_typename(OBJECT(child)));
876

    
877
    object_property_add(obj, name, type, object_get_child_property,
878
                        NULL, object_finalize_child_property, child, errp);
879

    
880
    object_ref(child);
881
    g_assert(child->parent == NULL);
882
    child->parent = obj;
883

    
884
    g_free(type);
885
}
886

    
887
static void object_get_link_property(Object *obj, Visitor *v, void *opaque,
888
                                     const char *name, Error **errp)
889
{
890
    Object **child = opaque;
891
    gchar *path;
892

    
893
    if (*child) {
894
        path = object_get_canonical_path(*child);
895
        visit_type_str(v, &path, name, errp);
896
        g_free(path);
897
    } else {
898
        path = (gchar *)"";
899
        visit_type_str(v, &path, name, errp);
900
    }
901
}
902

    
903
static void object_set_link_property(Object *obj, Visitor *v, void *opaque,
904
                                     const char *name, Error **errp)
905
{
906
    Object **child = opaque;
907
    Object *old_target;
908
    bool ambiguous = false;
909
    const char *type;
910
    char *path;
911
    gchar *target_type;
912

    
913
    type = object_property_get_type(obj, name, NULL);
914

    
915
    visit_type_str(v, &path, name, errp);
916

    
917
    old_target = *child;
918
    *child = NULL;
919

    
920
    if (strcmp(path, "") != 0) {
921
        Object *target;
922

    
923
        /* Go from link<FOO> to FOO.  */
924
        target_type = g_strndup(&type[5], strlen(type) - 6);
925
        target = object_resolve_path_type(path, target_type, &ambiguous);
926

    
927
        if (ambiguous) {
928
            error_set(errp, QERR_AMBIGUOUS_PATH, path);
929
        } else if (target) {
930
            object_ref(target);
931
            *child = target;
932
        } else {
933
            target = object_resolve_path(path, &ambiguous);
934
            if (target || ambiguous) {
935
                error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, target_type);
936
            } else {
937
                error_set(errp, QERR_DEVICE_NOT_FOUND, path);
938
            }
939
        }
940
        g_free(target_type);
941
    }
942

    
943
    g_free(path);
944

    
945
    if (old_target != NULL) {
946
        object_unref(old_target);
947
    }
948
}
949

    
950
void object_property_add_link(Object *obj, const char *name,
951
                              const char *type, Object **child,
952
                              Error **errp)
953
{
954
    gchar *full_type;
955

    
956
    full_type = g_strdup_printf("link<%s>", type);
957

    
958
    object_property_add(obj, name, full_type,
959
                        object_get_link_property,
960
                        object_set_link_property,
961
                        NULL, child, errp);
962

    
963
    g_free(full_type);
964
}
965

    
966
gchar *object_get_canonical_path(Object *obj)
967
{
968
    Object *root = object_get_root();
969
    char *newpath = NULL, *path = NULL;
970

    
971
    if (object_is_type(obj, type_interface)) {
972
        obj = INTERFACE(obj)->obj;
973
    }
974

    
975
    while (obj != root) {
976
        ObjectProperty *prop = NULL;
977

    
978
        g_assert(obj->parent != NULL);
979

    
980
        QTAILQ_FOREACH(prop, &obj->parent->properties, node) {
981
            if (!strstart(prop->type, "child<", NULL)) {
982
                continue;
983
            }
984

    
985
            if (prop->opaque == obj) {
986
                if (path) {
987
                    newpath = g_strdup_printf("%s/%s", prop->name, path);
988
                    g_free(path);
989
                    path = newpath;
990
                } else {
991
                    path = g_strdup(prop->name);
992
                }
993
                break;
994
            }
995
        }
996

    
997
        g_assert(prop != NULL);
998

    
999
        obj = obj->parent;
1000
    }
1001

    
1002
    newpath = g_strdup_printf("/%s", path);
1003
    g_free(path);
1004

    
1005
    return newpath;
1006
}
1007

    
1008
static Object *object_resolve_abs_path(Object *parent,
1009
                                          gchar **parts,
1010
                                          const char *typename,
1011
                                          int index)
1012
{
1013
    ObjectProperty *prop;
1014
    Object *child;
1015

    
1016
    if (parts[index] == NULL) {
1017
        return object_dynamic_cast(parent, typename);
1018
    }
1019

    
1020
    if (strcmp(parts[index], "") == 0) {
1021
        return object_resolve_abs_path(parent, parts, typename, index + 1);
1022
    }
1023

    
1024
    prop = object_property_find(parent, parts[index]);
1025
    if (prop == NULL) {
1026
        return NULL;
1027
    }
1028

    
1029
    child = NULL;
1030
    if (strstart(prop->type, "link<", NULL)) {
1031
        Object **pchild = prop->opaque;
1032
        if (*pchild) {
1033
            child = *pchild;
1034
        }
1035
    } else if (strstart(prop->type, "child<", NULL)) {
1036
        child = prop->opaque;
1037
    }
1038

    
1039
    if (!child) {
1040
        return NULL;
1041
    }
1042

    
1043
    return object_resolve_abs_path(child, parts, typename, index + 1);
1044
}
1045

    
1046
static Object *object_resolve_partial_path(Object *parent,
1047
                                              gchar **parts,
1048
                                              const char *typename,
1049
                                              bool *ambiguous)
1050
{
1051
    Object *obj;
1052
    ObjectProperty *prop;
1053

    
1054
    obj = object_resolve_abs_path(parent, parts, typename, 0);
1055

    
1056
    QTAILQ_FOREACH(prop, &parent->properties, node) {
1057
        Object *found;
1058

    
1059
        if (!strstart(prop->type, "child<", NULL)) {
1060
            continue;
1061
        }
1062

    
1063
        found = object_resolve_partial_path(prop->opaque, parts,
1064
                                            typename, ambiguous);
1065
        if (found) {
1066
            if (obj) {
1067
                if (ambiguous) {
1068
                    *ambiguous = true;
1069
                }
1070
                return NULL;
1071
            }
1072
            obj = found;
1073
        }
1074

    
1075
        if (ambiguous && *ambiguous) {
1076
            return NULL;
1077
        }
1078
    }
1079

    
1080
    return obj;
1081
}
1082

    
1083
Object *object_resolve_path_type(const char *path, const char *typename,
1084
                                 bool *ambiguous)
1085
{
1086
    bool partial_path = true;
1087
    Object *obj;
1088
    gchar **parts;
1089

    
1090
    parts = g_strsplit(path, "/", 0);
1091
    if (parts == NULL || parts[0] == NULL) {
1092
        g_strfreev(parts);
1093
        return object_get_root();
1094
    }
1095

    
1096
    if (strcmp(parts[0], "") == 0) {
1097
        partial_path = false;
1098
    }
1099

    
1100
    if (partial_path) {
1101
        if (ambiguous) {
1102
            *ambiguous = false;
1103
        }
1104
        obj = object_resolve_partial_path(object_get_root(), parts,
1105
                                          typename, ambiguous);
1106
    } else {
1107
        obj = object_resolve_abs_path(object_get_root(), parts, typename, 1);
1108
    }
1109

    
1110
    g_strfreev(parts);
1111

    
1112
    return obj;
1113
}
1114

    
1115
Object *object_resolve_path(const char *path, bool *ambiguous)
1116
{
1117
    return object_resolve_path_type(path, TYPE_OBJECT, ambiguous);
1118
}
1119

    
1120
typedef struct StringProperty
1121
{
1122
    char *(*get)(Object *, Error **);
1123
    void (*set)(Object *, const char *, Error **);
1124
} StringProperty;
1125

    
1126
static void property_get_str(Object *obj, Visitor *v, void *opaque,
1127
                             const char *name, Error **errp)
1128
{
1129
    StringProperty *prop = opaque;
1130
    char *value;
1131

    
1132
    value = prop->get(obj, errp);
1133
    if (value) {
1134
        visit_type_str(v, &value, name, errp);
1135
        g_free(value);
1136
    }
1137
}
1138

    
1139
static void property_set_str(Object *obj, Visitor *v, void *opaque,
1140
                             const char *name, Error **errp)
1141
{
1142
    StringProperty *prop = opaque;
1143
    char *value;
1144
    Error *local_err = NULL;
1145

    
1146
    visit_type_str(v, &value, name, &local_err);
1147
    if (local_err) {
1148
        error_propagate(errp, local_err);
1149
        return;
1150
    }
1151

    
1152
    prop->set(obj, value, errp);
1153
    g_free(value);
1154
}
1155

    
1156
static void property_release_str(Object *obj, const char *name,
1157
                                 void *opaque)
1158
{
1159
    StringProperty *prop = opaque;
1160
    g_free(prop);
1161
}
1162

    
1163
void object_property_add_str(Object *obj, const char *name,
1164
                           char *(*get)(Object *, Error **),
1165
                           void (*set)(Object *, const char *, Error **),
1166
                           Error **errp)
1167
{
1168
    StringProperty *prop = g_malloc0(sizeof(*prop));
1169

    
1170
    prop->get = get;
1171
    prop->set = set;
1172

    
1173
    object_property_add(obj, name, "string",
1174
                        get ? property_get_str : NULL,
1175
                        set ? property_set_str : NULL,
1176
                        property_release_str,
1177
                        prop, errp);
1178
}