Statistics
| Branch: | Revision:

root / qom / object.c @ 5d9d3f47

History | View | Annotate | Download (28.7 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_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

    
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_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

    
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 inline bool object_property_is_child(ObjectProperty *prop)
300
{
301
    return strstart(prop->type, "child<", NULL);
302
}
303

    
304
static inline bool object_property_is_link(ObjectProperty *prop)
305
{
306
    return strstart(prop->type, "link<", NULL);
307
}
308

    
309
static void object_property_del_all(Object *obj)
310
{
311
    while (!QTAILQ_EMPTY(&obj->properties)) {
312
        ObjectProperty *prop = QTAILQ_FIRST(&obj->properties);
313

    
314
        QTAILQ_REMOVE(&obj->properties, prop, node);
315

    
316
        if (prop->release) {
317
            prop->release(obj, prop->name, prop->opaque);
318
        }
319

    
320
        g_free(prop->name);
321
        g_free(prop->type);
322
        g_free(prop);
323
    }
324
}
325

    
326
static void object_property_del_child(Object *obj, Object *child, Error **errp)
327
{
328
    ObjectProperty *prop;
329

    
330
    QTAILQ_FOREACH(prop, &obj->properties, node) {
331
        if (object_property_is_child(prop) && prop->opaque == child) {
332
            object_property_del(obj, prop->name, errp);
333
            break;
334
        }
335
    }
336
}
337

    
338
void object_unparent(Object *obj)
339
{
340
    if (obj->parent) {
341
        object_property_del_child(obj->parent, obj, NULL);
342
    }
343
}
344

    
345
static void object_deinit(Object *obj, TypeImpl *type)
346
{
347
    if (type->instance_finalize) {
348
        type->instance_finalize(obj);
349
    }
350

    
351
    while (obj->interfaces) {
352
        Interface *iface_obj = obj->interfaces->data;
353
        obj->interfaces = g_slist_delete_link(obj->interfaces, obj->interfaces);
354
        object_delete(OBJECT(iface_obj));
355
    }
356

    
357
    if (type_has_parent(type)) {
358
        object_deinit(obj, type_get_parent(type));
359
    }
360

    
361
    object_unparent(obj);
362
}
363

    
364
void object_finalize(void *data)
365
{
366
    Object *obj = data;
367
    TypeImpl *ti = obj->class->type;
368

    
369
    object_deinit(obj, ti);
370
    object_property_del_all(obj);
371

    
372
    g_assert(obj->ref == 0);
373
}
374

    
375
Object *object_new_with_type(Type type)
376
{
377
    Object *obj;
378

    
379
    g_assert(type != NULL);
380
    type_initialize(type);
381

    
382
    obj = g_malloc(type->instance_size);
383
    object_initialize_with_type(obj, type);
384
    object_ref(obj);
385

    
386
    return obj;
387
}
388

    
389
Object *object_new(const char *typename)
390
{
391
    TypeImpl *ti = type_get_by_name(typename);
392

    
393
    return object_new_with_type(ti);
394
}
395

    
396
void object_delete(Object *obj)
397
{
398
    object_unref(obj);
399
    g_assert(obj->ref == 0);
400
    g_free(obj);
401
}
402

    
403
static bool type_is_ancestor(TypeImpl *type, TypeImpl *target_type)
404
{
405
    assert(target_type);
406

    
407
    /* Check if typename is a direct ancestor of type */
408
    while (type) {
409
        if (type == target_type) {
410
            return true;
411
        }
412

    
413
        type = type_get_parent(type);
414
    }
415

    
416
    return false;
417
}
418

    
419
static bool object_is_type(Object *obj, TypeImpl *target_type)
420
{
421
    return !target_type || type_is_ancestor(obj->class->type, target_type);
422
}
423

    
424
Object *object_dynamic_cast(Object *obj, const char *typename)
425
{
426
    TypeImpl *target_type = type_get_by_name(typename);
427
    GSList *i;
428

    
429
    /* Check if typename is a direct ancestor.  Special-case TYPE_OBJECT,
430
     * we want to go back from interfaces to the parent.
431
    */
432
    if (target_type && object_is_type(obj, target_type)) {
433
        return obj;
434
    }
435

    
436
    /* Check if obj is an interface and its containing object is a direct
437
     * ancestor of typename.  In principle we could do this test at the very
438
     * beginning of object_dynamic_cast, avoiding a second call to
439
     * object_is_type.  However, casting between interfaces is relatively
440
     * rare, and object_is_type(obj, type_interface) would fail almost always.
441
     *
442
     * Perhaps we could add a magic value to the object header for increased
443
     * (run-time) type safety and to speed up tests like this one.  If we ever
444
     * do that we can revisit the order here.
445
     */
446
    if (object_is_type(obj, type_interface)) {
447
        assert(!obj->interfaces);
448
        obj = INTERFACE(obj)->obj;
449
        if (object_is_type(obj, target_type)) {
450
            return obj;
451
        }
452
    }
453

    
454
    if (!target_type) {
455
        return obj;
456
    }
457

    
458
    /* Check if obj has an interface of typename */
459
    for (i = obj->interfaces; i; i = i->next) {
460
        Interface *iface = i->data;
461

    
462
        if (object_is_type(OBJECT(iface), target_type)) {
463
            return OBJECT(iface);
464
        }
465
    }
466

    
467
    return NULL;
468
}
469

    
470

    
471
static void register_types(void)
472
{
473
    static TypeInfo interface_info = {
474
        .name = TYPE_INTERFACE,
475
        .instance_size = sizeof(Interface),
476
        .abstract = true,
477
    };
478

    
479
    type_interface = type_register_static(&interface_info);
480
}
481

    
482
type_init(register_types)
483

    
484
Object *object_dynamic_cast_assert(Object *obj, const char *typename)
485
{
486
    Object *inst;
487

    
488
    inst = object_dynamic_cast(obj, typename);
489

    
490
    if (!inst) {
491
        fprintf(stderr, "Object %p is not an instance of type %s\n",
492
                obj, typename);
493
        abort();
494
    }
495

    
496
    return inst;
497
}
498

    
499
ObjectClass *object_class_dynamic_cast(ObjectClass *class,
500
                                       const char *typename)
501
{
502
    TypeImpl *target_type = type_get_by_name(typename);
503
    TypeImpl *type = class->type;
504

    
505
    while (type) {
506
        if (type == target_type) {
507
            return class;
508
        }
509

    
510
        type = type_get_parent(type);
511
    }
512

    
513
    return NULL;
514
}
515

    
516
ObjectClass *object_class_dynamic_cast_assert(ObjectClass *class,
517
                                              const char *typename)
518
{
519
    ObjectClass *ret = object_class_dynamic_cast(class, typename);
520

    
521
    if (!ret) {
522
        fprintf(stderr, "Object %p is not an instance of type %s\n",
523
                class, typename);
524
        abort();
525
    }
526

    
527
    return ret;
528
}
529

    
530
const char *object_get_typename(Object *obj)
531
{
532
    return obj->class->type->name;
533
}
534

    
535
ObjectClass *object_get_class(Object *obj)
536
{
537
    return obj->class;
538
}
539

    
540
const char *object_class_get_name(ObjectClass *klass)
541
{
542
    return klass->type->name;
543
}
544

    
545
ObjectClass *object_class_by_name(const char *typename)
546
{
547
    TypeImpl *type = type_get_by_name(typename);
548

    
549
    if (!type) {
550
        return NULL;
551
    }
552

    
553
    type_initialize(type);
554

    
555
    return type->class;
556
}
557

    
558
ObjectClass *object_class_get_parent(ObjectClass *class)
559
{
560
    TypeImpl *type = type_get_parent(class->type);
561

    
562
    if (!type) {
563
        return NULL;
564
    }
565

    
566
    type_initialize(type);
567

    
568
    return type->class;
569
}
570

    
571
typedef struct OCFData
572
{
573
    void (*fn)(ObjectClass *klass, void *opaque);
574
    const char *implements_type;
575
    bool include_abstract;
576
    void *opaque;
577
} OCFData;
578

    
579
static void object_class_foreach_tramp(gpointer key, gpointer value,
580
                                       gpointer opaque)
581
{
582
    OCFData *data = opaque;
583
    TypeImpl *type = value;
584
    ObjectClass *k;
585

    
586
    type_initialize(type);
587
    k = type->class;
588

    
589
    if (!data->include_abstract && type->abstract) {
590
        return;
591
    }
592

    
593
    if (data->implements_type && 
594
        !object_class_dynamic_cast(k, data->implements_type)) {
595
        return;
596
    }
597

    
598
    data->fn(k, data->opaque);
599
}
600

    
601
void object_class_foreach(void (*fn)(ObjectClass *klass, void *opaque),
602
                          const char *implements_type, bool include_abstract,
603
                          void *opaque)
604
{
605
    OCFData data = { fn, implements_type, include_abstract, opaque };
606

    
607
    g_hash_table_foreach(type_table_get(), object_class_foreach_tramp, &data);
608
}
609

    
610
static void object_class_get_list_tramp(ObjectClass *klass, void *opaque)
611
{
612
    GSList **list = opaque;
613

    
614
    *list = g_slist_prepend(*list, klass);
615
}
616

    
617
GSList *object_class_get_list(const char *implements_type,
618
                              bool include_abstract)
619
{
620
    GSList *list = NULL;
621

    
622
    object_class_foreach(object_class_get_list_tramp,
623
                         implements_type, include_abstract, &list);
624
    return list;
625
}
626

    
627
void object_ref(Object *obj)
628
{
629
    obj->ref++;
630
}
631

    
632
void object_unref(Object *obj)
633
{
634
    g_assert(obj->ref > 0);
635
    obj->ref--;
636

    
637
    /* parent always holds a reference to its children */
638
    if (obj->ref == 0) {
639
        object_finalize(obj);
640
    }
641
}
642

    
643
void object_property_add(Object *obj, const char *name, const char *type,
644
                         ObjectPropertyAccessor *get,
645
                         ObjectPropertyAccessor *set,
646
                         ObjectPropertyRelease *release,
647
                         void *opaque, Error **errp)
648
{
649
    ObjectProperty *prop = g_malloc0(sizeof(*prop));
650

    
651
    prop->name = g_strdup(name);
652
    prop->type = g_strdup(type);
653

    
654
    prop->get = get;
655
    prop->set = set;
656
    prop->release = release;
657
    prop->opaque = opaque;
658

    
659
    QTAILQ_INSERT_TAIL(&obj->properties, prop, node);
660
}
661

    
662
static ObjectProperty *object_property_find(Object *obj, const char *name)
663
{
664
    ObjectProperty *prop;
665

    
666
    QTAILQ_FOREACH(prop, &obj->properties, node) {
667
        if (strcmp(prop->name, name) == 0) {
668
            return prop;
669
        }
670
    }
671

    
672
    return NULL;
673
}
674

    
675
void object_property_del(Object *obj, const char *name, Error **errp)
676
{
677
    ObjectProperty *prop = object_property_find(obj, name);
678

    
679
    QTAILQ_REMOVE(&obj->properties, prop, node);
680

    
681
    prop->release(obj, prop->name, prop->opaque);
682

    
683
    g_free(prop->name);
684
    g_free(prop->type);
685
    g_free(prop);
686
}
687

    
688
void object_property_get(Object *obj, Visitor *v, const char *name,
689
                         Error **errp)
690
{
691
    ObjectProperty *prop = object_property_find(obj, name);
692

    
693
    if (prop == NULL) {
694
        error_set(errp, QERR_PROPERTY_NOT_FOUND, "", name);
695
        return;
696
    }
697

    
698
    if (!prop->get) {
699
        error_set(errp, QERR_PERMISSION_DENIED);
700
    } else {
701
        prop->get(obj, v, prop->opaque, name, errp);
702
    }
703
}
704

    
705
void object_property_set(Object *obj, Visitor *v, const char *name,
706
                         Error **errp)
707
{
708
    ObjectProperty *prop = object_property_find(obj, name);
709

    
710
    if (prop == NULL) {
711
        error_set(errp, QERR_PROPERTY_NOT_FOUND, "", name);
712
        return;
713
    }
714

    
715
    if (!prop->set) {
716
        error_set(errp, QERR_PERMISSION_DENIED);
717
    } else {
718
        prop->set(obj, v, prop->opaque, name, errp);
719
    }
720
}
721

    
722
void object_property_set_str(Object *obj, const char *value,
723
                             const char *name, Error **errp)
724
{
725
    QString *qstr = qstring_from_str(value);
726
    object_property_set_qobject(obj, QOBJECT(qstr), name, errp);
727

    
728
    QDECREF(qstr);
729
}
730

    
731
char *object_property_get_str(Object *obj, const char *name,
732
                              Error **errp)
733
{
734
    QObject *ret = object_property_get_qobject(obj, name, errp);
735
    QString *qstring;
736
    char *retval;
737

    
738
    if (!ret) {
739
        return NULL;
740
    }
741
    qstring = qobject_to_qstring(ret);
742
    if (!qstring) {
743
        error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, "string");
744
        retval = NULL;
745
    } else {
746
        retval = g_strdup(qstring_get_str(qstring));
747
    }
748

    
749
    QDECREF(qstring);
750
    return retval;
751
}
752

    
753
void object_property_set_link(Object *obj, Object *value,
754
                              const char *name, Error **errp)
755
{
756
    object_property_set_str(obj, object_get_canonical_path(value),
757
                            name, errp);
758
}
759

    
760
Object *object_property_get_link(Object *obj, const char *name,
761
                                 Error **errp)
762
{
763
    char *str = object_property_get_str(obj, name, errp);
764
    Object *target = NULL;
765

    
766
    if (str && *str) {
767
        target = object_resolve_path(str, NULL);
768
        if (!target) {
769
            error_set(errp, QERR_DEVICE_NOT_FOUND, str);
770
        }
771
    }
772

    
773
    g_free(str);
774
    return target;
775
}
776

    
777
void object_property_set_bool(Object *obj, bool value,
778
                              const char *name, Error **errp)
779
{
780
    QBool *qbool = qbool_from_int(value);
781
    object_property_set_qobject(obj, QOBJECT(qbool), name, errp);
782

    
783
    QDECREF(qbool);
784
}
785

    
786
bool object_property_get_bool(Object *obj, const char *name,
787
                              Error **errp)
788
{
789
    QObject *ret = object_property_get_qobject(obj, name, errp);
790
    QBool *qbool;
791
    bool retval;
792

    
793
    if (!ret) {
794
        return false;
795
    }
796
    qbool = qobject_to_qbool(ret);
797
    if (!qbool) {
798
        error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, "boolean");
799
        retval = false;
800
    } else {
801
        retval = qbool_get_int(qbool);
802
    }
803

    
804
    QDECREF(qbool);
805
    return retval;
806
}
807

    
808
void object_property_set_int(Object *obj, int64_t value,
809
                             const char *name, Error **errp)
810
{
811
    QInt *qint = qint_from_int(value);
812
    object_property_set_qobject(obj, QOBJECT(qint), name, errp);
813

    
814
    QDECREF(qint);
815
}
816

    
817
int64_t object_property_get_int(Object *obj, const char *name,
818
                                Error **errp)
819
{
820
    QObject *ret = object_property_get_qobject(obj, name, errp);
821
    QInt *qint;
822
    int64_t retval;
823

    
824
    if (!ret) {
825
        return -1;
826
    }
827
    qint = qobject_to_qint(ret);
828
    if (!qint) {
829
        error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, "int");
830
        retval = -1;
831
    } else {
832
        retval = qint_get_int(qint);
833
    }
834

    
835
    QDECREF(qint);
836
    return retval;
837
}
838

    
839
void object_property_parse(Object *obj, const char *string,
840
                           const char *name, Error **errp)
841
{
842
    StringInputVisitor *mi;
843
    mi = string_input_visitor_new(string);
844
    object_property_set(obj, string_input_get_visitor(mi), name, errp);
845

    
846
    string_input_visitor_cleanup(mi);
847
}
848

    
849
char *object_property_print(Object *obj, const char *name,
850
                            Error **errp)
851
{
852
    StringOutputVisitor *mo;
853
    char *string;
854

    
855
    mo = string_output_visitor_new();
856
    object_property_get(obj, string_output_get_visitor(mo), name, errp);
857
    string = string_output_get_string(mo);
858
    string_output_visitor_cleanup(mo);
859
    return string;
860
}
861

    
862
const char *object_property_get_type(Object *obj, const char *name, Error **errp)
863
{
864
    ObjectProperty *prop = object_property_find(obj, name);
865

    
866
    if (prop == NULL) {
867
        error_set(errp, QERR_PROPERTY_NOT_FOUND, "", name);
868
        return NULL;
869
    }
870

    
871
    return prop->type;
872
}
873

    
874
Object *object_get_root(void)
875
{
876
    static Object *root;
877

    
878
    if (!root) {
879
        root = object_new("container");
880
    }
881

    
882
    return root;
883
}
884

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

    
891
    path = object_get_canonical_path(child);
892
    visit_type_str(v, &path, name, errp);
893
    g_free(path);
894
}
895

    
896
static void object_finalize_child_property(Object *obj, const char *name,
897
                                           void *opaque)
898
{
899
    Object *child = opaque;
900

    
901
    object_unref(child);
902
}
903

    
904
void object_property_add_child(Object *obj, const char *name,
905
                               Object *child, Error **errp)
906
{
907
    gchar *type;
908

    
909
    /* Registering an interface object in the composition tree will mightily
910
     * confuse object_get_canonical_path (which, on the other hand, knows how
911
     * to get the canonical path of an interface object).
912
     */
913
    assert(!object_is_type(obj, type_interface));
914

    
915
    type = g_strdup_printf("child<%s>", object_get_typename(OBJECT(child)));
916

    
917
    object_property_add(obj, name, type, object_get_child_property,
918
                        NULL, object_finalize_child_property, child, errp);
919

    
920
    object_ref(child);
921
    g_assert(child->parent == NULL);
922
    child->parent = obj;
923

    
924
    g_free(type);
925
}
926

    
927
static void object_get_link_property(Object *obj, Visitor *v, void *opaque,
928
                                     const char *name, Error **errp)
929
{
930
    Object **child = opaque;
931
    gchar *path;
932

    
933
    if (*child) {
934
        path = object_get_canonical_path(*child);
935
        visit_type_str(v, &path, name, errp);
936
        g_free(path);
937
    } else {
938
        path = (gchar *)"";
939
        visit_type_str(v, &path, name, errp);
940
    }
941
}
942

    
943
static void object_set_link_property(Object *obj, Visitor *v, void *opaque,
944
                                     const char *name, Error **errp)
945
{
946
    Object **child = opaque;
947
    Object *old_target;
948
    bool ambiguous = false;
949
    const char *type;
950
    char *path;
951
    gchar *target_type;
952

    
953
    type = object_property_get_type(obj, name, NULL);
954

    
955
    visit_type_str(v, &path, name, errp);
956

    
957
    old_target = *child;
958
    *child = NULL;
959

    
960
    if (strcmp(path, "") != 0) {
961
        Object *target;
962

    
963
        /* Go from link<FOO> to FOO.  */
964
        target_type = g_strndup(&type[5], strlen(type) - 6);
965
        target = object_resolve_path_type(path, target_type, &ambiguous);
966

    
967
        if (ambiguous) {
968
            error_set(errp, QERR_AMBIGUOUS_PATH, path);
969
        } else if (target) {
970
            object_ref(target);
971
            *child = target;
972
        } else {
973
            target = object_resolve_path(path, &ambiguous);
974
            if (target || ambiguous) {
975
                error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, target_type);
976
            } else {
977
                error_set(errp, QERR_DEVICE_NOT_FOUND, path);
978
            }
979
        }
980
        g_free(target_type);
981
    }
982

    
983
    g_free(path);
984

    
985
    if (old_target != NULL) {
986
        object_unref(old_target);
987
    }
988
}
989

    
990
void object_property_add_link(Object *obj, const char *name,
991
                              const char *type, Object **child,
992
                              Error **errp)
993
{
994
    gchar *full_type;
995

    
996
    full_type = g_strdup_printf("link<%s>", type);
997

    
998
    object_property_add(obj, name, full_type,
999
                        object_get_link_property,
1000
                        object_set_link_property,
1001
                        NULL, child, errp);
1002

    
1003
    g_free(full_type);
1004
}
1005

    
1006
gchar *object_get_canonical_path(Object *obj)
1007
{
1008
    Object *root = object_get_root();
1009
    char *newpath = NULL, *path = NULL;
1010

    
1011
    if (object_is_type(obj, type_interface)) {
1012
        obj = INTERFACE(obj)->obj;
1013
    }
1014

    
1015
    while (obj != root) {
1016
        ObjectProperty *prop = NULL;
1017

    
1018
        g_assert(obj->parent != NULL);
1019

    
1020
        QTAILQ_FOREACH(prop, &obj->parent->properties, node) {
1021
            if (!object_property_is_child(prop)) {
1022
                continue;
1023
            }
1024

    
1025
            if (prop->opaque == obj) {
1026
                if (path) {
1027
                    newpath = g_strdup_printf("%s/%s", prop->name, path);
1028
                    g_free(path);
1029
                    path = newpath;
1030
                } else {
1031
                    path = g_strdup(prop->name);
1032
                }
1033
                break;
1034
            }
1035
        }
1036

    
1037
        g_assert(prop != NULL);
1038

    
1039
        obj = obj->parent;
1040
    }
1041

    
1042
    newpath = g_strdup_printf("/%s", path);
1043
    g_free(path);
1044

    
1045
    return newpath;
1046
}
1047

    
1048
Object *object_resolve_path_component(Object *parent, gchar *part)
1049
{
1050
    ObjectProperty *prop = object_property_find(parent, part);
1051
    if (prop == NULL) {
1052
        return NULL;
1053
    }
1054

    
1055
    if (object_property_is_link(prop)) {
1056
        return *(Object **)prop->opaque;
1057
    } else if (object_property_is_child(prop)) {
1058
        return prop->opaque;
1059
    } else {
1060
        return NULL;
1061
    }
1062
}
1063

    
1064
static Object *object_resolve_abs_path(Object *parent,
1065
                                          gchar **parts,
1066
                                          const char *typename,
1067
                                          int index)
1068
{
1069
    Object *child;
1070

    
1071
    if (parts[index] == NULL) {
1072
        return object_dynamic_cast(parent, typename);
1073
    }
1074

    
1075
    if (strcmp(parts[index], "") == 0) {
1076
        return object_resolve_abs_path(parent, parts, typename, index + 1);
1077
    }
1078

    
1079
    child = object_resolve_path_component(parent, parts[index]);
1080
    if (!child) {
1081
        return NULL;
1082
    }
1083

    
1084
    return object_resolve_abs_path(child, parts, typename, index + 1);
1085
}
1086

    
1087
static Object *object_resolve_partial_path(Object *parent,
1088
                                              gchar **parts,
1089
                                              const char *typename,
1090
                                              bool *ambiguous)
1091
{
1092
    Object *obj;
1093
    ObjectProperty *prop;
1094

    
1095
    obj = object_resolve_abs_path(parent, parts, typename, 0);
1096

    
1097
    QTAILQ_FOREACH(prop, &parent->properties, node) {
1098
        Object *found;
1099

    
1100
        if (!object_property_is_child(prop)) {
1101
            continue;
1102
        }
1103

    
1104
        found = object_resolve_partial_path(prop->opaque, parts,
1105
                                            typename, ambiguous);
1106
        if (found) {
1107
            if (obj) {
1108
                if (ambiguous) {
1109
                    *ambiguous = true;
1110
                }
1111
                return NULL;
1112
            }
1113
            obj = found;
1114
        }
1115

    
1116
        if (ambiguous && *ambiguous) {
1117
            return NULL;
1118
        }
1119
    }
1120

    
1121
    return obj;
1122
}
1123

    
1124
Object *object_resolve_path_type(const char *path, const char *typename,
1125
                                 bool *ambiguous)
1126
{
1127
    bool partial_path = true;
1128
    Object *obj;
1129
    gchar **parts;
1130

    
1131
    parts = g_strsplit(path, "/", 0);
1132
    if (parts == NULL || parts[0] == NULL) {
1133
        g_strfreev(parts);
1134
        return object_get_root();
1135
    }
1136

    
1137
    if (strcmp(parts[0], "") == 0) {
1138
        partial_path = false;
1139
    }
1140

    
1141
    if (partial_path) {
1142
        if (ambiguous) {
1143
            *ambiguous = false;
1144
        }
1145
        obj = object_resolve_partial_path(object_get_root(), parts,
1146
                                          typename, ambiguous);
1147
    } else {
1148
        obj = object_resolve_abs_path(object_get_root(), parts, typename, 1);
1149
    }
1150

    
1151
    g_strfreev(parts);
1152

    
1153
    return obj;
1154
}
1155

    
1156
Object *object_resolve_path(const char *path, bool *ambiguous)
1157
{
1158
    return object_resolve_path_type(path, TYPE_OBJECT, ambiguous);
1159
}
1160

    
1161
typedef struct StringProperty
1162
{
1163
    char *(*get)(Object *, Error **);
1164
    void (*set)(Object *, const char *, Error **);
1165
} StringProperty;
1166

    
1167
static void property_get_str(Object *obj, Visitor *v, void *opaque,
1168
                             const char *name, Error **errp)
1169
{
1170
    StringProperty *prop = opaque;
1171
    char *value;
1172

    
1173
    value = prop->get(obj, errp);
1174
    if (value) {
1175
        visit_type_str(v, &value, name, errp);
1176
        g_free(value);
1177
    }
1178
}
1179

    
1180
static void property_set_str(Object *obj, Visitor *v, void *opaque,
1181
                             const char *name, Error **errp)
1182
{
1183
    StringProperty *prop = opaque;
1184
    char *value;
1185
    Error *local_err = NULL;
1186

    
1187
    visit_type_str(v, &value, name, &local_err);
1188
    if (local_err) {
1189
        error_propagate(errp, local_err);
1190
        return;
1191
    }
1192

    
1193
    prop->set(obj, value, errp);
1194
    g_free(value);
1195
}
1196

    
1197
static void property_release_str(Object *obj, const char *name,
1198
                                 void *opaque)
1199
{
1200
    StringProperty *prop = opaque;
1201
    g_free(prop);
1202
}
1203

    
1204
void object_property_add_str(Object *obj, const char *name,
1205
                           char *(*get)(Object *, Error **),
1206
                           void (*set)(Object *, const char *, Error **),
1207
                           Error **errp)
1208
{
1209
    StringProperty *prop = g_malloc0(sizeof(*prop));
1210

    
1211
    prop->get = get;
1212
    prop->set = set;
1213

    
1214
    object_property_add(obj, name, "string",
1215
                        get ? property_get_str : NULL,
1216
                        set ? property_set_str : NULL,
1217
                        property_release_str,
1218
                        prop, errp);
1219
}