Statistics
| Branch: | Revision:

root / qom / object.c @ 17862378

History | View | Annotate | Download (30 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 "qom/object.h"
14
#include "qemu-common.h"
15
#include "qapi/visitor.h"
16
#include "qapi/string-input-visitor.h"
17
#include "qapi/string-output-visitor.h"
18
#include "qapi/qmp/qerror.h"
19

    
20
/* TODO: replace QObject with a simpler visitor to avoid a dependency
21
 * of the QOM core on QObject?  */
22
#include "qom/qom-qobject.h"
23
#include "qapi/qmp/qobject.h"
24
#include "qapi/qmp/qbool.h"
25
#include "qapi/qmp/qint.h"
26
#include "qapi/qmp/qstring.h"
27

    
28
#define MAX_INTERFACES 32
29

    
30
typedef struct InterfaceImpl InterfaceImpl;
31
typedef struct TypeImpl TypeImpl;
32

    
33
struct InterfaceImpl
34
{
35
    const char *typename;
36
};
37

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

    
42
    size_t class_size;
43

    
44
    size_t instance_size;
45

    
46
    void (*class_init)(ObjectClass *klass, void *data);
47
    void (*class_base_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
static Type type_interface;
67

    
68
static GHashTable *type_table_get(void)
69
{
70
    static GHashTable *type_table;
71

    
72
    if (type_table == NULL) {
73
        type_table = g_hash_table_new(g_str_hash, g_str_equal);
74
    }
75

    
76
    return type_table;
77
}
78

    
79
static void type_table_add(TypeImpl *ti)
80
{
81
    g_hash_table_insert(type_table_get(), (void *)ti->name, ti);
82
}
83

    
84
static TypeImpl *type_table_lookup(const char *name)
85
{
86
    return g_hash_table_lookup(type_table_get(), name);
87
}
88

    
89
static TypeImpl *type_register_internal(const TypeInfo *info)
90
{
91
    TypeImpl *ti = g_malloc0(sizeof(*ti));
92
    int i;
93

    
94
    g_assert(info->name != NULL);
95

    
96
    if (type_table_lookup(info->name) != NULL) {
97
        fprintf(stderr, "Registering `%s' which already exists\n", info->name);
98
        abort();
99
    }
100

    
101
    ti->name = g_strdup(info->name);
102
    ti->parent = g_strdup(info->parent);
103

    
104
    ti->class_size = info->class_size;
105
    ti->instance_size = info->instance_size;
106

    
107
    ti->class_init = info->class_init;
108
    ti->class_base_init = info->class_base_init;
109
    ti->class_finalize = info->class_finalize;
110
    ti->class_data = info->class_data;
111

    
112
    ti->instance_init = info->instance_init;
113
    ti->instance_finalize = info->instance_finalize;
114

    
115
    ti->abstract = info->abstract;
116

    
117
    for (i = 0; info->interfaces && info->interfaces[i].type; i++) {
118
        ti->interfaces[i].typename = g_strdup(info->interfaces[i].type);
119
    }
120
    ti->num_interfaces = i;
121

    
122
    type_table_add(ti);
123

    
124
    return ti;
125
}
126

    
127
TypeImpl *type_register(const TypeInfo *info)
128
{
129
    assert(info->parent);
130
    return type_register_internal(info);
131
}
132

    
133
TypeImpl *type_register_static(const TypeInfo *info)
134
{
135
    return type_register(info);
136
}
137

    
138
static TypeImpl *type_get_by_name(const char *name)
139
{
140
    if (name == NULL) {
141
        return NULL;
142
    }
143

    
144
    return type_table_lookup(name);
145
}
146

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

    
154
    return type->parent_type;
155
}
156

    
157
static bool type_has_parent(TypeImpl *type)
158
{
159
    return (type->parent != NULL);
160
}
161

    
162
static size_t type_class_get_size(TypeImpl *ti)
163
{
164
    if (ti->class_size) {
165
        return ti->class_size;
166
    }
167

    
168
    if (type_has_parent(ti)) {
169
        return type_class_get_size(type_get_parent(ti));
170
    }
171

    
172
    return sizeof(ObjectClass);
173
}
174

    
175
static size_t type_object_get_size(TypeImpl *ti)
176
{
177
    if (ti->instance_size) {
178
        return ti->instance_size;
179
    }
180

    
181
    if (type_has_parent(ti)) {
182
        return type_object_get_size(type_get_parent(ti));
183
    }
184

    
185
    return 0;
186
}
187

    
188
static bool type_is_ancestor(TypeImpl *type, TypeImpl *target_type)
189
{
190
    assert(target_type);
191

    
192
    /* Check if typename is a direct ancestor of type */
193
    while (type) {
194
        if (type == target_type) {
195
            return true;
196
        }
197

    
198
        type = type_get_parent(type);
199
    }
200

    
201
    return false;
202
}
203

    
204
static void type_initialize(TypeImpl *ti);
205

    
206
static void type_initialize_interface(TypeImpl *ti, const char *parent)
207
{
208
    InterfaceClass *new_iface;
209
    TypeInfo info = { };
210
    TypeImpl *iface_impl;
211

    
212
    info.parent = parent;
213
    info.name = g_strdup_printf("%s::%s", ti->name, info.parent);
214
    info.abstract = true;
215

    
216
    iface_impl = type_register(&info);
217
    type_initialize(iface_impl);
218
    g_free((char *)info.name);
219

    
220
    new_iface = (InterfaceClass *)iface_impl->class;
221
    new_iface->concrete_class = ti->class;
222

    
223
    ti->class->interfaces = g_slist_append(ti->class->interfaces,
224
                                           iface_impl->class);
225
}
226

    
227
static void type_initialize(TypeImpl *ti)
228
{
229
    TypeImpl *parent;
230

    
231
    if (ti->class) {
232
        return;
233
    }
234

    
235
    ti->class_size = type_class_get_size(ti);
236
    ti->instance_size = type_object_get_size(ti);
237

    
238
    ti->class = g_malloc0(ti->class_size);
239

    
240
    parent = type_get_parent(ti);
241
    if (parent) {
242
        type_initialize(parent);
243
        GSList *e;
244
        int i;
245

    
246
        g_assert(parent->class_size <= ti->class_size);
247
        memcpy(ti->class, parent->class, parent->class_size);
248

    
249
        for (e = parent->class->interfaces; e; e = e->next) {
250
            ObjectClass *iface = e->data;
251
            type_initialize_interface(ti, object_class_get_name(iface));
252
        }
253

    
254
        for (i = 0; i < ti->num_interfaces; i++) {
255
            TypeImpl *t = type_get_by_name(ti->interfaces[i].typename);
256
            for (e = ti->class->interfaces; e; e = e->next) {
257
                TypeImpl *target_type = OBJECT_CLASS(e->data)->type;
258

    
259
                if (type_is_ancestor(target_type, t)) {
260
                    break;
261
                }
262
            }
263

    
264
            if (e) {
265
                continue;
266
            }
267

    
268
            type_initialize_interface(ti, ti->interfaces[i].typename);
269
        }
270
    }
271

    
272
    ti->class->type = ti;
273

    
274
    while (parent) {
275
        if (parent->class_base_init) {
276
            parent->class_base_init(ti->class, ti->class_data);
277
        }
278
        parent = type_get_parent(parent);
279
    }
280

    
281
    if (ti->class_init) {
282
        ti->class_init(ti->class, ti->class_data);
283
    }
284

    
285

    
286
}
287

    
288
static void object_init_with_type(Object *obj, TypeImpl *ti)
289
{
290
    if (type_has_parent(ti)) {
291
        object_init_with_type(obj, type_get_parent(ti));
292
    }
293

    
294
    if (ti->instance_init) {
295
        ti->instance_init(obj);
296
    }
297
}
298

    
299
void object_initialize_with_type(void *data, TypeImpl *type)
300
{
301
    Object *obj = data;
302

    
303
    g_assert(type != NULL);
304
    type_initialize(type);
305

    
306
    g_assert(type->instance_size >= sizeof(Object));
307
    g_assert(type->abstract == false);
308

    
309
    memset(obj, 0, type->instance_size);
310
    obj->class = type->class;
311
    object_ref(obj);
312
    QTAILQ_INIT(&obj->properties);
313
    object_init_with_type(obj, type);
314
}
315

    
316
void object_initialize(void *data, const char *typename)
317
{
318
    TypeImpl *type = type_get_by_name(typename);
319

    
320
    object_initialize_with_type(data, type);
321
}
322

    
323
static inline bool object_property_is_child(ObjectProperty *prop)
324
{
325
    return strstart(prop->type, "child<", NULL);
326
}
327

    
328
static inline bool object_property_is_link(ObjectProperty *prop)
329
{
330
    return strstart(prop->type, "link<", NULL);
331
}
332

    
333
static void object_property_del_all(Object *obj)
334
{
335
    while (!QTAILQ_EMPTY(&obj->properties)) {
336
        ObjectProperty *prop = QTAILQ_FIRST(&obj->properties);
337

    
338
        QTAILQ_REMOVE(&obj->properties, prop, node);
339

    
340
        if (prop->release) {
341
            prop->release(obj, prop->name, prop->opaque);
342
        }
343

    
344
        g_free(prop->name);
345
        g_free(prop->type);
346
        g_free(prop);
347
    }
348
}
349

    
350
static void object_property_del_child(Object *obj, Object *child, Error **errp)
351
{
352
    ObjectProperty *prop;
353

    
354
    QTAILQ_FOREACH(prop, &obj->properties, node) {
355
        if (object_property_is_child(prop) && prop->opaque == child) {
356
            object_property_del(obj, prop->name, errp);
357
            break;
358
        }
359
    }
360
}
361

    
362
void object_unparent(Object *obj)
363
{
364
    if (obj->parent) {
365
        object_property_del_child(obj->parent, obj, NULL);
366
    }
367
    if (obj->class->unparent) {
368
        (obj->class->unparent)(obj);
369
    }
370
}
371

    
372
static void object_deinit(Object *obj, TypeImpl *type)
373
{
374
    if (type->instance_finalize) {
375
        type->instance_finalize(obj);
376
    }
377

    
378
    if (type_has_parent(type)) {
379
        object_deinit(obj, type_get_parent(type));
380
    }
381
}
382

    
383
static void object_finalize(void *data)
384
{
385
    Object *obj = data;
386
    TypeImpl *ti = obj->class->type;
387

    
388
    object_deinit(obj, ti);
389
    object_property_del_all(obj);
390

    
391
    g_assert(obj->ref == 0);
392
    if (obj->free) {
393
        obj->free(obj);
394
    }
395
}
396

    
397
Object *object_new_with_type(Type type)
398
{
399
    Object *obj;
400

    
401
    g_assert(type != NULL);
402
    type_initialize(type);
403

    
404
    obj = g_malloc(type->instance_size);
405
    object_initialize_with_type(obj, type);
406
    obj->free = g_free;
407

    
408
    return obj;
409
}
410

    
411
Object *object_new(const char *typename)
412
{
413
    TypeImpl *ti = type_get_by_name(typename);
414

    
415
    return object_new_with_type(ti);
416
}
417

    
418
void object_delete(Object *obj)
419
{
420
    object_unparent(obj);
421
    g_assert(obj->ref == 1);
422
    object_unref(obj);
423
}
424

    
425
Object *object_dynamic_cast(Object *obj, const char *typename)
426
{
427
    if (obj && object_class_dynamic_cast(object_get_class(obj), typename)) {
428
        return obj;
429
    }
430

    
431
    return NULL;
432
}
433

    
434
Object *object_dynamic_cast_assert(Object *obj, const char *typename)
435
{
436
    Object *inst;
437

    
438
    inst = object_dynamic_cast(obj, typename);
439

    
440
    if (!inst && obj) {
441
        fprintf(stderr, "Object %p is not an instance of type %s\n",
442
                obj, typename);
443
        abort();
444
    }
445

    
446
    return inst;
447
}
448

    
449
ObjectClass *object_class_dynamic_cast(ObjectClass *class,
450
                                       const char *typename)
451
{
452
    TypeImpl *target_type = type_get_by_name(typename);
453
    TypeImpl *type = class->type;
454
    ObjectClass *ret = NULL;
455

    
456
    if (type->num_interfaces && type_is_ancestor(target_type, type_interface)) {
457
        int found = 0;
458
        GSList *i;
459

    
460
        for (i = class->interfaces; i; i = i->next) {
461
            ObjectClass *target_class = i->data;
462

    
463
            if (type_is_ancestor(target_class->type, target_type)) {
464
                ret = target_class;
465
                found++;
466
            }
467
         }
468

    
469
        /* The match was ambiguous, don't allow a cast */
470
        if (found > 1) {
471
            ret = NULL;
472
        }
473
    } else if (type_is_ancestor(type, target_type)) {
474
        ret = class;
475
    }
476

    
477
    return ret;
478
}
479

    
480
ObjectClass *object_class_dynamic_cast_assert(ObjectClass *class,
481
                                              const char *typename)
482
{
483
    ObjectClass *ret = object_class_dynamic_cast(class, typename);
484

    
485
    if (!ret) {
486
        fprintf(stderr, "Object %p is not an instance of type %s\n",
487
                class, typename);
488
        abort();
489
    }
490

    
491
    return ret;
492
}
493

    
494
const char *object_get_typename(Object *obj)
495
{
496
    return obj->class->type->name;
497
}
498

    
499
ObjectClass *object_get_class(Object *obj)
500
{
501
    return obj->class;
502
}
503

    
504
bool object_class_is_abstract(ObjectClass *klass)
505
{
506
    return klass->type->abstract;
507
}
508

    
509
const char *object_class_get_name(ObjectClass *klass)
510
{
511
    return klass->type->name;
512
}
513

    
514
ObjectClass *object_class_by_name(const char *typename)
515
{
516
    TypeImpl *type = type_get_by_name(typename);
517

    
518
    if (!type) {
519
        return NULL;
520
    }
521

    
522
    type_initialize(type);
523

    
524
    return type->class;
525
}
526

    
527
ObjectClass *object_class_get_parent(ObjectClass *class)
528
{
529
    TypeImpl *type = type_get_parent(class->type);
530

    
531
    if (!type) {
532
        return NULL;
533
    }
534

    
535
    type_initialize(type);
536

    
537
    return type->class;
538
}
539

    
540
typedef struct OCFData
541
{
542
    void (*fn)(ObjectClass *klass, void *opaque);
543
    const char *implements_type;
544
    bool include_abstract;
545
    void *opaque;
546
} OCFData;
547

    
548
static void object_class_foreach_tramp(gpointer key, gpointer value,
549
                                       gpointer opaque)
550
{
551
    OCFData *data = opaque;
552
    TypeImpl *type = value;
553
    ObjectClass *k;
554

    
555
    type_initialize(type);
556
    k = type->class;
557

    
558
    if (!data->include_abstract && type->abstract) {
559
        return;
560
    }
561

    
562
    if (data->implements_type && 
563
        !object_class_dynamic_cast(k, data->implements_type)) {
564
        return;
565
    }
566

    
567
    data->fn(k, data->opaque);
568
}
569

    
570
void object_class_foreach(void (*fn)(ObjectClass *klass, void *opaque),
571
                          const char *implements_type, bool include_abstract,
572
                          void *opaque)
573
{
574
    OCFData data = { fn, implements_type, include_abstract, opaque };
575

    
576
    g_hash_table_foreach(type_table_get(), object_class_foreach_tramp, &data);
577
}
578

    
579
int object_child_foreach(Object *obj, int (*fn)(Object *child, void *opaque),
580
                         void *opaque)
581
{
582
    ObjectProperty *prop;
583
    int ret = 0;
584

    
585
    QTAILQ_FOREACH(prop, &obj->properties, node) {
586
        if (object_property_is_child(prop)) {
587
            ret = fn(prop->opaque, opaque);
588
            if (ret != 0) {
589
                break;
590
            }
591
        }
592
    }
593
    return ret;
594
}
595

    
596
static void object_class_get_list_tramp(ObjectClass *klass, void *opaque)
597
{
598
    GSList **list = opaque;
599

    
600
    *list = g_slist_prepend(*list, klass);
601
}
602

    
603
GSList *object_class_get_list(const char *implements_type,
604
                              bool include_abstract)
605
{
606
    GSList *list = NULL;
607

    
608
    object_class_foreach(object_class_get_list_tramp,
609
                         implements_type, include_abstract, &list);
610
    return list;
611
}
612

    
613
void object_ref(Object *obj)
614
{
615
    obj->ref++;
616
}
617

    
618
void object_unref(Object *obj)
619
{
620
    g_assert(obj->ref > 0);
621
    obj->ref--;
622

    
623
    /* parent always holds a reference to its children */
624
    if (obj->ref == 0) {
625
        object_finalize(obj);
626
    }
627
}
628

    
629
void object_property_add(Object *obj, const char *name, const char *type,
630
                         ObjectPropertyAccessor *get,
631
                         ObjectPropertyAccessor *set,
632
                         ObjectPropertyRelease *release,
633
                         void *opaque, Error **errp)
634
{
635
    ObjectProperty *prop = g_malloc0(sizeof(*prop));
636

    
637
    prop->name = g_strdup(name);
638
    prop->type = g_strdup(type);
639

    
640
    prop->get = get;
641
    prop->set = set;
642
    prop->release = release;
643
    prop->opaque = opaque;
644

    
645
    QTAILQ_INSERT_TAIL(&obj->properties, prop, node);
646
}
647

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

    
653
    QTAILQ_FOREACH(prop, &obj->properties, node) {
654
        if (strcmp(prop->name, name) == 0) {
655
            return prop;
656
        }
657
    }
658

    
659
    error_set(errp, QERR_PROPERTY_NOT_FOUND, "", name);
660
    return NULL;
661
}
662

    
663
void object_property_del(Object *obj, const char *name, Error **errp)
664
{
665
    ObjectProperty *prop = object_property_find(obj, name, errp);
666
    if (prop == NULL) {
667
        return;
668
    }
669

    
670
    if (prop->release) {
671
        prop->release(obj, name, prop->opaque);
672
    }
673

    
674
    QTAILQ_REMOVE(&obj->properties, prop, node);
675

    
676
    g_free(prop->name);
677
    g_free(prop->type);
678
    g_free(prop);
679
}
680

    
681
void object_property_get(Object *obj, Visitor *v, const char *name,
682
                         Error **errp)
683
{
684
    ObjectProperty *prop = object_property_find(obj, name, errp);
685
    if (prop == NULL) {
686
        return;
687
    }
688

    
689
    if (!prop->get) {
690
        error_set(errp, QERR_PERMISSION_DENIED);
691
    } else {
692
        prop->get(obj, v, prop->opaque, name, errp);
693
    }
694
}
695

    
696
void object_property_set(Object *obj, Visitor *v, const char *name,
697
                         Error **errp)
698
{
699
    ObjectProperty *prop = object_property_find(obj, name, errp);
700
    if (prop == NULL) {
701
        return;
702
    }
703

    
704
    if (!prop->set) {
705
        error_set(errp, QERR_PERMISSION_DENIED);
706
    } else {
707
        prop->set(obj, v, prop->opaque, name, errp);
708
    }
709
}
710

    
711
void object_property_set_str(Object *obj, const char *value,
712
                             const char *name, Error **errp)
713
{
714
    QString *qstr = qstring_from_str(value);
715
    object_property_set_qobject(obj, QOBJECT(qstr), name, errp);
716

    
717
    QDECREF(qstr);
718
}
719

    
720
char *object_property_get_str(Object *obj, const char *name,
721
                              Error **errp)
722
{
723
    QObject *ret = object_property_get_qobject(obj, name, errp);
724
    QString *qstring;
725
    char *retval;
726

    
727
    if (!ret) {
728
        return NULL;
729
    }
730
    qstring = qobject_to_qstring(ret);
731
    if (!qstring) {
732
        error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, "string");
733
        retval = NULL;
734
    } else {
735
        retval = g_strdup(qstring_get_str(qstring));
736
    }
737

    
738
    QDECREF(qstring);
739
    return retval;
740
}
741

    
742
void object_property_set_link(Object *obj, Object *value,
743
                              const char *name, Error **errp)
744
{
745
    object_property_set_str(obj, object_get_canonical_path(value),
746
                            name, errp);
747
}
748

    
749
Object *object_property_get_link(Object *obj, const char *name,
750
                                 Error **errp)
751
{
752
    char *str = object_property_get_str(obj, name, errp);
753
    Object *target = NULL;
754

    
755
    if (str && *str) {
756
        target = object_resolve_path(str, NULL);
757
        if (!target) {
758
            error_set(errp, QERR_DEVICE_NOT_FOUND, str);
759
        }
760
    }
761

    
762
    g_free(str);
763
    return target;
764
}
765

    
766
void object_property_set_bool(Object *obj, bool value,
767
                              const char *name, Error **errp)
768
{
769
    QBool *qbool = qbool_from_int(value);
770
    object_property_set_qobject(obj, QOBJECT(qbool), name, errp);
771

    
772
    QDECREF(qbool);
773
}
774

    
775
bool object_property_get_bool(Object *obj, const char *name,
776
                              Error **errp)
777
{
778
    QObject *ret = object_property_get_qobject(obj, name, errp);
779
    QBool *qbool;
780
    bool retval;
781

    
782
    if (!ret) {
783
        return false;
784
    }
785
    qbool = qobject_to_qbool(ret);
786
    if (!qbool) {
787
        error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, "boolean");
788
        retval = false;
789
    } else {
790
        retval = qbool_get_int(qbool);
791
    }
792

    
793
    QDECREF(qbool);
794
    return retval;
795
}
796

    
797
void object_property_set_int(Object *obj, int64_t value,
798
                             const char *name, Error **errp)
799
{
800
    QInt *qint = qint_from_int(value);
801
    object_property_set_qobject(obj, QOBJECT(qint), name, errp);
802

    
803
    QDECREF(qint);
804
}
805

    
806
int64_t object_property_get_int(Object *obj, const char *name,
807
                                Error **errp)
808
{
809
    QObject *ret = object_property_get_qobject(obj, name, errp);
810
    QInt *qint;
811
    int64_t retval;
812

    
813
    if (!ret) {
814
        return -1;
815
    }
816
    qint = qobject_to_qint(ret);
817
    if (!qint) {
818
        error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, "int");
819
        retval = -1;
820
    } else {
821
        retval = qint_get_int(qint);
822
    }
823

    
824
    QDECREF(qint);
825
    return retval;
826
}
827

    
828
void object_property_parse(Object *obj, const char *string,
829
                           const char *name, Error **errp)
830
{
831
    StringInputVisitor *mi;
832
    mi = string_input_visitor_new(string);
833
    object_property_set(obj, string_input_get_visitor(mi), name, errp);
834

    
835
    string_input_visitor_cleanup(mi);
836
}
837

    
838
char *object_property_print(Object *obj, const char *name,
839
                            Error **errp)
840
{
841
    StringOutputVisitor *mo;
842
    char *string;
843

    
844
    mo = string_output_visitor_new();
845
    object_property_get(obj, string_output_get_visitor(mo), name, errp);
846
    string = string_output_get_string(mo);
847
    string_output_visitor_cleanup(mo);
848
    return string;
849
}
850

    
851
const char *object_property_get_type(Object *obj, const char *name, Error **errp)
852
{
853
    ObjectProperty *prop = object_property_find(obj, name, errp);
854
    if (prop == NULL) {
855
        return NULL;
856
    }
857

    
858
    return prop->type;
859
}
860

    
861
Object *object_get_root(void)
862
{
863
    static Object *root;
864

    
865
    if (!root) {
866
        root = object_new("container");
867
    }
868

    
869
    return root;
870
}
871

    
872
static void object_get_child_property(Object *obj, Visitor *v, void *opaque,
873
                                      const char *name, Error **errp)
874
{
875
    Object *child = opaque;
876
    gchar *path;
877

    
878
    path = object_get_canonical_path(child);
879
    visit_type_str(v, &path, name, errp);
880
    g_free(path);
881
}
882

    
883
static void object_finalize_child_property(Object *obj, const char *name,
884
                                           void *opaque)
885
{
886
    Object *child = opaque;
887

    
888
    object_unref(child);
889
}
890

    
891
void object_property_add_child(Object *obj, const char *name,
892
                               Object *child, Error **errp)
893
{
894
    gchar *type;
895

    
896
    type = g_strdup_printf("child<%s>", object_get_typename(OBJECT(child)));
897

    
898
    object_property_add(obj, name, type, object_get_child_property,
899
                        NULL, object_finalize_child_property, child, errp);
900

    
901
    object_ref(child);
902
    g_assert(child->parent == NULL);
903
    child->parent = obj;
904

    
905
    g_free(type);
906
}
907

    
908
static void object_get_link_property(Object *obj, Visitor *v, void *opaque,
909
                                     const char *name, Error **errp)
910
{
911
    Object **child = opaque;
912
    gchar *path;
913

    
914
    if (*child) {
915
        path = object_get_canonical_path(*child);
916
        visit_type_str(v, &path, name, errp);
917
        g_free(path);
918
    } else {
919
        path = (gchar *)"";
920
        visit_type_str(v, &path, name, errp);
921
    }
922
}
923

    
924
static void object_set_link_property(Object *obj, Visitor *v, void *opaque,
925
                                     const char *name, Error **errp)
926
{
927
    Object **child = opaque;
928
    Object *old_target;
929
    bool ambiguous = false;
930
    const char *type;
931
    char *path;
932
    gchar *target_type;
933

    
934
    type = object_property_get_type(obj, name, NULL);
935

    
936
    visit_type_str(v, &path, name, errp);
937

    
938
    old_target = *child;
939
    *child = NULL;
940

    
941
    if (strcmp(path, "") != 0) {
942
        Object *target;
943

    
944
        /* Go from link<FOO> to FOO.  */
945
        target_type = g_strndup(&type[5], strlen(type) - 6);
946
        target = object_resolve_path_type(path, target_type, &ambiguous);
947

    
948
        if (ambiguous) {
949
            error_set(errp, QERR_AMBIGUOUS_PATH, path);
950
        } else if (target) {
951
            object_ref(target);
952
            *child = target;
953
        } else {
954
            target = object_resolve_path(path, &ambiguous);
955
            if (target || ambiguous) {
956
                error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, target_type);
957
            } else {
958
                error_set(errp, QERR_DEVICE_NOT_FOUND, path);
959
            }
960
        }
961
        g_free(target_type);
962
    }
963

    
964
    g_free(path);
965

    
966
    if (old_target != NULL) {
967
        object_unref(old_target);
968
    }
969
}
970

    
971
void object_property_add_link(Object *obj, const char *name,
972
                              const char *type, Object **child,
973
                              Error **errp)
974
{
975
    gchar *full_type;
976

    
977
    full_type = g_strdup_printf("link<%s>", type);
978

    
979
    object_property_add(obj, name, full_type,
980
                        object_get_link_property,
981
                        object_set_link_property,
982
                        NULL, child, errp);
983

    
984
    g_free(full_type);
985
}
986

    
987
gchar *object_get_canonical_path(Object *obj)
988
{
989
    Object *root = object_get_root();
990
    char *newpath = NULL, *path = NULL;
991

    
992
    while (obj != root) {
993
        ObjectProperty *prop = NULL;
994

    
995
        g_assert(obj->parent != NULL);
996

    
997
        QTAILQ_FOREACH(prop, &obj->parent->properties, node) {
998
            if (!object_property_is_child(prop)) {
999
                continue;
1000
            }
1001

    
1002
            if (prop->opaque == obj) {
1003
                if (path) {
1004
                    newpath = g_strdup_printf("%s/%s", prop->name, path);
1005
                    g_free(path);
1006
                    path = newpath;
1007
                } else {
1008
                    path = g_strdup(prop->name);
1009
                }
1010
                break;
1011
            }
1012
        }
1013

    
1014
        g_assert(prop != NULL);
1015

    
1016
        obj = obj->parent;
1017
    }
1018

    
1019
    newpath = g_strdup_printf("/%s", path);
1020
    g_free(path);
1021

    
1022
    return newpath;
1023
}
1024

    
1025
Object *object_resolve_path_component(Object *parent, const gchar *part)
1026
{
1027
    ObjectProperty *prop = object_property_find(parent, part, NULL);
1028
    if (prop == NULL) {
1029
        return NULL;
1030
    }
1031

    
1032
    if (object_property_is_link(prop)) {
1033
        return *(Object **)prop->opaque;
1034
    } else if (object_property_is_child(prop)) {
1035
        return prop->opaque;
1036
    } else {
1037
        return NULL;
1038
    }
1039
}
1040

    
1041
static Object *object_resolve_abs_path(Object *parent,
1042
                                          gchar **parts,
1043
                                          const char *typename,
1044
                                          int index)
1045
{
1046
    Object *child;
1047

    
1048
    if (parts[index] == NULL) {
1049
        return object_dynamic_cast(parent, typename);
1050
    }
1051

    
1052
    if (strcmp(parts[index], "") == 0) {
1053
        return object_resolve_abs_path(parent, parts, typename, index + 1);
1054
    }
1055

    
1056
    child = object_resolve_path_component(parent, parts[index]);
1057
    if (!child) {
1058
        return NULL;
1059
    }
1060

    
1061
    return object_resolve_abs_path(child, parts, typename, index + 1);
1062
}
1063

    
1064
static Object *object_resolve_partial_path(Object *parent,
1065
                                              gchar **parts,
1066
                                              const char *typename,
1067
                                              bool *ambiguous)
1068
{
1069
    Object *obj;
1070
    ObjectProperty *prop;
1071

    
1072
    obj = object_resolve_abs_path(parent, parts, typename, 0);
1073

    
1074
    QTAILQ_FOREACH(prop, &parent->properties, node) {
1075
        Object *found;
1076

    
1077
        if (!object_property_is_child(prop)) {
1078
            continue;
1079
        }
1080

    
1081
        found = object_resolve_partial_path(prop->opaque, parts,
1082
                                            typename, ambiguous);
1083
        if (found) {
1084
            if (obj) {
1085
                if (ambiguous) {
1086
                    *ambiguous = true;
1087
                }
1088
                return NULL;
1089
            }
1090
            obj = found;
1091
        }
1092

    
1093
        if (ambiguous && *ambiguous) {
1094
            return NULL;
1095
        }
1096
    }
1097

    
1098
    return obj;
1099
}
1100

    
1101
Object *object_resolve_path_type(const char *path, const char *typename,
1102
                                 bool *ambiguous)
1103
{
1104
    bool partial_path = true;
1105
    Object *obj;
1106
    gchar **parts;
1107

    
1108
    parts = g_strsplit(path, "/", 0);
1109
    if (parts == NULL || parts[0] == NULL) {
1110
        g_strfreev(parts);
1111
        return object_get_root();
1112
    }
1113

    
1114
    if (strcmp(parts[0], "") == 0) {
1115
        partial_path = false;
1116
    }
1117

    
1118
    if (partial_path) {
1119
        if (ambiguous) {
1120
            *ambiguous = false;
1121
        }
1122
        obj = object_resolve_partial_path(object_get_root(), parts,
1123
                                          typename, ambiguous);
1124
    } else {
1125
        obj = object_resolve_abs_path(object_get_root(), parts, typename, 1);
1126
    }
1127

    
1128
    g_strfreev(parts);
1129

    
1130
    return obj;
1131
}
1132

    
1133
Object *object_resolve_path(const char *path, bool *ambiguous)
1134
{
1135
    return object_resolve_path_type(path, TYPE_OBJECT, ambiguous);
1136
}
1137

    
1138
typedef struct StringProperty
1139
{
1140
    char *(*get)(Object *, Error **);
1141
    void (*set)(Object *, const char *, Error **);
1142
} StringProperty;
1143

    
1144
static void property_get_str(Object *obj, Visitor *v, void *opaque,
1145
                             const char *name, Error **errp)
1146
{
1147
    StringProperty *prop = opaque;
1148
    char *value;
1149

    
1150
    value = prop->get(obj, errp);
1151
    if (value) {
1152
        visit_type_str(v, &value, name, errp);
1153
        g_free(value);
1154
    }
1155
}
1156

    
1157
static void property_set_str(Object *obj, Visitor *v, void *opaque,
1158
                             const char *name, Error **errp)
1159
{
1160
    StringProperty *prop = opaque;
1161
    char *value;
1162
    Error *local_err = NULL;
1163

    
1164
    visit_type_str(v, &value, name, &local_err);
1165
    if (local_err) {
1166
        error_propagate(errp, local_err);
1167
        return;
1168
    }
1169

    
1170
    prop->set(obj, value, errp);
1171
    g_free(value);
1172
}
1173

    
1174
static void property_release_str(Object *obj, const char *name,
1175
                                 void *opaque)
1176
{
1177
    StringProperty *prop = opaque;
1178
    g_free(prop);
1179
}
1180

    
1181
void object_property_add_str(Object *obj, const char *name,
1182
                           char *(*get)(Object *, Error **),
1183
                           void (*set)(Object *, const char *, Error **),
1184
                           Error **errp)
1185
{
1186
    StringProperty *prop = g_malloc0(sizeof(*prop));
1187

    
1188
    prop->get = get;
1189
    prop->set = set;
1190

    
1191
    object_property_add(obj, name, "string",
1192
                        get ? property_get_str : NULL,
1193
                        set ? property_set_str : NULL,
1194
                        property_release_str,
1195
                        prop, errp);
1196
}
1197

    
1198
typedef struct BoolProperty
1199
{
1200
    bool (*get)(Object *, Error **);
1201
    void (*set)(Object *, bool, Error **);
1202
} BoolProperty;
1203

    
1204
static void property_get_bool(Object *obj, Visitor *v, void *opaque,
1205
                              const char *name, Error **errp)
1206
{
1207
    BoolProperty *prop = opaque;
1208
    bool value;
1209

    
1210
    value = prop->get(obj, errp);
1211
    visit_type_bool(v, &value, name, errp);
1212
}
1213

    
1214
static void property_set_bool(Object *obj, Visitor *v, void *opaque,
1215
                              const char *name, Error **errp)
1216
{
1217
    BoolProperty *prop = opaque;
1218
    bool value;
1219
    Error *local_err = NULL;
1220

    
1221
    visit_type_bool(v, &value, name, &local_err);
1222
    if (local_err) {
1223
        error_propagate(errp, local_err);
1224
        return;
1225
    }
1226

    
1227
    prop->set(obj, value, errp);
1228
}
1229

    
1230
static void property_release_bool(Object *obj, const char *name,
1231
                                  void *opaque)
1232
{
1233
    BoolProperty *prop = opaque;
1234
    g_free(prop);
1235
}
1236

    
1237
void object_property_add_bool(Object *obj, const char *name,
1238
                              bool (*get)(Object *, Error **),
1239
                              void (*set)(Object *, bool, Error **),
1240
                              Error **errp)
1241
{
1242
    BoolProperty *prop = g_malloc0(sizeof(*prop));
1243

    
1244
    prop->get = get;
1245
    prop->set = set;
1246

    
1247
    object_property_add(obj, name, "bool",
1248
                        get ? property_get_bool : NULL,
1249
                        set ? property_set_bool : NULL,
1250
                        property_release_bool,
1251
                        prop, errp);
1252
}
1253

    
1254
static char *qdev_get_type(Object *obj, Error **errp)
1255
{
1256
    return g_strdup(object_get_typename(obj));
1257
}
1258

    
1259
static void object_instance_init(Object *obj)
1260
{
1261
    object_property_add_str(obj, "type", qdev_get_type, NULL, NULL);
1262
}
1263

    
1264
static void register_types(void)
1265
{
1266
    static TypeInfo interface_info = {
1267
        .name = TYPE_INTERFACE,
1268
        .class_size = sizeof(InterfaceClass),
1269
        .abstract = true,
1270
    };
1271

    
1272
    static TypeInfo object_info = {
1273
        .name = TYPE_OBJECT,
1274
        .instance_size = sizeof(Object),
1275
        .instance_init = object_instance_init,
1276
        .abstract = true,
1277
    };
1278

    
1279
    type_interface = type_register_internal(&interface_info);
1280
    type_register_internal(&object_info);
1281
}
1282

    
1283
type_init(register_types)