Statistics
| Branch: | Revision:

root / qom / object.c @ e998fa8d

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
        ti->class->interfaces = NULL;
249

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

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

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

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

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

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

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

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

    
286

    
287
}
288

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

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

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

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

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

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

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

    
321
    object_initialize_with_type(data, type);
322
}
323

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

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

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

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

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

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

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

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

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

    
375
static void object_deinit(Object *obj, TypeImpl *type)
376
{
377
    if (type->instance_finalize) {
378
        type->instance_finalize(obj);
379
    }
380

    
381
    if (type_has_parent(type)) {
382
        object_deinit(obj, type_get_parent(type));
383
    }
384
}
385

    
386
static void object_finalize(void *data)
387
{
388
    Object *obj = data;
389
    TypeImpl *ti = obj->class->type;
390

    
391
    object_deinit(obj, ti);
392
    object_property_del_all(obj);
393

    
394
    g_assert(obj->ref == 0);
395
    if (obj->free) {
396
        obj->free(obj);
397
    }
398
}
399

    
400
Object *object_new_with_type(Type type)
401
{
402
    Object *obj;
403

    
404
    g_assert(type != NULL);
405
    type_initialize(type);
406

    
407
    obj = g_malloc(type->instance_size);
408
    object_initialize_with_type(obj, type);
409
    obj->free = g_free;
410

    
411
    return obj;
412
}
413

    
414
Object *object_new(const char *typename)
415
{
416
    TypeImpl *ti = type_get_by_name(typename);
417

    
418
    return object_new_with_type(ti);
419
}
420

    
421
Object *object_dynamic_cast(Object *obj, const char *typename)
422
{
423
    if (obj && object_class_dynamic_cast(object_get_class(obj), typename)) {
424
        return obj;
425
    }
426

    
427
    return NULL;
428
}
429

    
430
Object *object_dynamic_cast_assert(Object *obj, const char *typename)
431
{
432
    Object *inst;
433

    
434
    inst = object_dynamic_cast(obj, typename);
435

    
436
    if (!inst && obj) {
437
        fprintf(stderr, "Object %p is not an instance of type %s\n",
438
                obj, typename);
439
        abort();
440
    }
441

    
442
    return inst;
443
}
444

    
445
ObjectClass *object_class_dynamic_cast(ObjectClass *class,
446
                                       const char *typename)
447
{
448
    TypeImpl *target_type = type_get_by_name(typename);
449
    TypeImpl *type = class->type;
450
    ObjectClass *ret = NULL;
451

    
452
    if (type->class->interfaces &&
453
            type_is_ancestor(target_type, type_interface)) {
454
        int found = 0;
455
        GSList *i;
456

    
457
        for (i = class->interfaces; i; i = i->next) {
458
            ObjectClass *target_class = i->data;
459

    
460
            if (type_is_ancestor(target_class->type, target_type)) {
461
                ret = target_class;
462
                found++;
463
            }
464
         }
465

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

    
474
    return ret;
475
}
476

    
477
ObjectClass *object_class_dynamic_cast_assert(ObjectClass *class,
478
                                              const char *typename)
479
{
480
    ObjectClass *ret = object_class_dynamic_cast(class, typename);
481

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

    
488
    return ret;
489
}
490

    
491
const char *object_get_typename(Object *obj)
492
{
493
    return obj->class->type->name;
494
}
495

    
496
ObjectClass *object_get_class(Object *obj)
497
{
498
    return obj->class;
499
}
500

    
501
bool object_class_is_abstract(ObjectClass *klass)
502
{
503
    return klass->type->abstract;
504
}
505

    
506
const char *object_class_get_name(ObjectClass *klass)
507
{
508
    return klass->type->name;
509
}
510

    
511
ObjectClass *object_class_by_name(const char *typename)
512
{
513
    TypeImpl *type = type_get_by_name(typename);
514

    
515
    if (!type) {
516
        return NULL;
517
    }
518

    
519
    type_initialize(type);
520

    
521
    return type->class;
522
}
523

    
524
ObjectClass *object_class_get_parent(ObjectClass *class)
525
{
526
    TypeImpl *type = type_get_parent(class->type);
527

    
528
    if (!type) {
529
        return NULL;
530
    }
531

    
532
    type_initialize(type);
533

    
534
    return type->class;
535
}
536

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

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

    
552
    type_initialize(type);
553
    k = type->class;
554

    
555
    if (!data->include_abstract && type->abstract) {
556
        return;
557
    }
558

    
559
    if (data->implements_type && 
560
        !object_class_dynamic_cast(k, data->implements_type)) {
561
        return;
562
    }
563

    
564
    data->fn(k, data->opaque);
565
}
566

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

    
573
    g_hash_table_foreach(type_table_get(), object_class_foreach_tramp, &data);
574
}
575

    
576
int object_child_foreach(Object *obj, int (*fn)(Object *child, void *opaque),
577
                         void *opaque)
578
{
579
    ObjectProperty *prop;
580
    int ret = 0;
581

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

    
593
static void object_class_get_list_tramp(ObjectClass *klass, void *opaque)
594
{
595
    GSList **list = opaque;
596

    
597
    *list = g_slist_prepend(*list, klass);
598
}
599

    
600
GSList *object_class_get_list(const char *implements_type,
601
                              bool include_abstract)
602
{
603
    GSList *list = NULL;
604

    
605
    object_class_foreach(object_class_get_list_tramp,
606
                         implements_type, include_abstract, &list);
607
    return list;
608
}
609

    
610
void object_ref(Object *obj)
611
{
612
    obj->ref++;
613
}
614

    
615
void object_unref(Object *obj)
616
{
617
    g_assert(obj->ref > 0);
618
    obj->ref--;
619

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

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

    
634
    prop->name = g_strdup(name);
635
    prop->type = g_strdup(type);
636

    
637
    prop->get = get;
638
    prop->set = set;
639
    prop->release = release;
640
    prop->opaque = opaque;
641

    
642
    QTAILQ_INSERT_TAIL(&obj->properties, prop, node);
643
}
644

    
645
ObjectProperty *object_property_find(Object *obj, const char *name,
646
                                     Error **errp)
647
{
648
    ObjectProperty *prop;
649

    
650
    QTAILQ_FOREACH(prop, &obj->properties, node) {
651
        if (strcmp(prop->name, name) == 0) {
652
            return prop;
653
        }
654
    }
655

    
656
    error_set(errp, QERR_PROPERTY_NOT_FOUND, "", name);
657
    return NULL;
658
}
659

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

    
667
    if (prop->release) {
668
        prop->release(obj, name, prop->opaque);
669
    }
670

    
671
    QTAILQ_REMOVE(&obj->properties, prop, node);
672

    
673
    g_free(prop->name);
674
    g_free(prop->type);
675
    g_free(prop);
676
}
677

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

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

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

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

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

    
714
    QDECREF(qstr);
715
}
716

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

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

    
735
    QDECREF(qstring);
736
    return retval;
737
}
738

    
739
void object_property_set_link(Object *obj, Object *value,
740
                              const char *name, Error **errp)
741
{
742
    object_property_set_str(obj, object_get_canonical_path(value),
743
                            name, errp);
744
}
745

    
746
Object *object_property_get_link(Object *obj, const char *name,
747
                                 Error **errp)
748
{
749
    char *str = object_property_get_str(obj, name, errp);
750
    Object *target = NULL;
751

    
752
    if (str && *str) {
753
        target = object_resolve_path(str, NULL);
754
        if (!target) {
755
            error_set(errp, QERR_DEVICE_NOT_FOUND, str);
756
        }
757
    }
758

    
759
    g_free(str);
760
    return target;
761
}
762

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

    
769
    QDECREF(qbool);
770
}
771

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

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

    
790
    QDECREF(qbool);
791
    return retval;
792
}
793

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

    
800
    QDECREF(qint);
801
}
802

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

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

    
821
    QDECREF(qint);
822
    return retval;
823
}
824

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

    
832
    string_input_visitor_cleanup(mi);
833
}
834

    
835
char *object_property_print(Object *obj, const char *name,
836
                            Error **errp)
837
{
838
    StringOutputVisitor *mo;
839
    char *string;
840

    
841
    mo = string_output_visitor_new();
842
    object_property_get(obj, string_output_get_visitor(mo), name, errp);
843
    string = string_output_get_string(mo);
844
    string_output_visitor_cleanup(mo);
845
    return string;
846
}
847

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

    
855
    return prop->type;
856
}
857

    
858
Object *object_get_root(void)
859
{
860
    static Object *root;
861

    
862
    if (!root) {
863
        root = object_new("container");
864
    }
865

    
866
    return root;
867
}
868

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

    
875
    path = object_get_canonical_path(child);
876
    visit_type_str(v, &path, name, errp);
877
    g_free(path);
878
}
879

    
880
static void object_finalize_child_property(Object *obj, const char *name,
881
                                           void *opaque)
882
{
883
    Object *child = opaque;
884

    
885
    object_unref(child);
886
}
887

    
888
void object_property_add_child(Object *obj, const char *name,
889
                               Object *child, Error **errp)
890
{
891
    gchar *type;
892

    
893
    type = g_strdup_printf("child<%s>", object_get_typename(OBJECT(child)));
894

    
895
    object_property_add(obj, name, type, object_get_child_property,
896
                        NULL, object_finalize_child_property, child, errp);
897

    
898
    object_ref(child);
899
    g_assert(child->parent == NULL);
900
    child->parent = obj;
901

    
902
    g_free(type);
903
}
904

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

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

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

    
931
    type = object_property_get_type(obj, name, NULL);
932

    
933
    visit_type_str(v, &path, name, errp);
934

    
935
    old_target = *child;
936
    *child = NULL;
937

    
938
    if (strcmp(path, "") != 0) {
939
        Object *target;
940

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

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

    
961
    g_free(path);
962

    
963
    if (old_target != NULL) {
964
        object_unref(old_target);
965
    }
966
}
967

    
968
void object_property_add_link(Object *obj, const char *name,
969
                              const char *type, Object **child,
970
                              Error **errp)
971
{
972
    gchar *full_type;
973

    
974
    full_type = g_strdup_printf("link<%s>", type);
975

    
976
    object_property_add(obj, name, full_type,
977
                        object_get_link_property,
978
                        object_set_link_property,
979
                        NULL, child, errp);
980

    
981
    g_free(full_type);
982
}
983

    
984
gchar *object_get_canonical_path(Object *obj)
985
{
986
    Object *root = object_get_root();
987
    char *newpath = NULL, *path = NULL;
988

    
989
    while (obj != root) {
990
        ObjectProperty *prop = NULL;
991

    
992
        g_assert(obj->parent != NULL);
993

    
994
        QTAILQ_FOREACH(prop, &obj->parent->properties, node) {
995
            if (!object_property_is_child(prop)) {
996
                continue;
997
            }
998

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

    
1011
        g_assert(prop != NULL);
1012

    
1013
        obj = obj->parent;
1014
    }
1015

    
1016
    newpath = g_strdup_printf("/%s", path);
1017
    g_free(path);
1018

    
1019
    return newpath;
1020
}
1021

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

    
1029
    if (object_property_is_link(prop)) {
1030
        return *(Object **)prop->opaque;
1031
    } else if (object_property_is_child(prop)) {
1032
        return prop->opaque;
1033
    } else {
1034
        return NULL;
1035
    }
1036
}
1037

    
1038
static Object *object_resolve_abs_path(Object *parent,
1039
                                          gchar **parts,
1040
                                          const char *typename,
1041
                                          int index)
1042
{
1043
    Object *child;
1044

    
1045
    if (parts[index] == NULL) {
1046
        return object_dynamic_cast(parent, typename);
1047
    }
1048

    
1049
    if (strcmp(parts[index], "") == 0) {
1050
        return object_resolve_abs_path(parent, parts, typename, index + 1);
1051
    }
1052

    
1053
    child = object_resolve_path_component(parent, parts[index]);
1054
    if (!child) {
1055
        return NULL;
1056
    }
1057

    
1058
    return object_resolve_abs_path(child, parts, typename, index + 1);
1059
}
1060

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

    
1069
    obj = object_resolve_abs_path(parent, parts, typename, 0);
1070

    
1071
    QTAILQ_FOREACH(prop, &parent->properties, node) {
1072
        Object *found;
1073

    
1074
        if (!object_property_is_child(prop)) {
1075
            continue;
1076
        }
1077

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

    
1090
        if (ambiguous && *ambiguous) {
1091
            return NULL;
1092
        }
1093
    }
1094

    
1095
    return obj;
1096
}
1097

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

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

    
1111
    if (strcmp(parts[0], "") == 0) {
1112
        partial_path = false;
1113
    }
1114

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

    
1125
    g_strfreev(parts);
1126

    
1127
    return obj;
1128
}
1129

    
1130
Object *object_resolve_path(const char *path, bool *ambiguous)
1131
{
1132
    return object_resolve_path_type(path, TYPE_OBJECT, ambiguous);
1133
}
1134

    
1135
typedef struct StringProperty
1136
{
1137
    char *(*get)(Object *, Error **);
1138
    void (*set)(Object *, const char *, Error **);
1139
} StringProperty;
1140

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

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

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

    
1161
    visit_type_str(v, &value, name, &local_err);
1162
    if (local_err) {
1163
        error_propagate(errp, local_err);
1164
        return;
1165
    }
1166

    
1167
    prop->set(obj, value, errp);
1168
    g_free(value);
1169
}
1170

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

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

    
1185
    prop->get = get;
1186
    prop->set = set;
1187

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

    
1195
typedef struct BoolProperty
1196
{
1197
    bool (*get)(Object *, Error **);
1198
    void (*set)(Object *, bool, Error **);
1199
} BoolProperty;
1200

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

    
1207
    value = prop->get(obj, errp);
1208
    visit_type_bool(v, &value, name, errp);
1209
}
1210

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

    
1218
    visit_type_bool(v, &value, name, &local_err);
1219
    if (local_err) {
1220
        error_propagate(errp, local_err);
1221
        return;
1222
    }
1223

    
1224
    prop->set(obj, value, errp);
1225
}
1226

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

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

    
1241
    prop->get = get;
1242
    prop->set = set;
1243

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

    
1251
static char *qdev_get_type(Object *obj, Error **errp)
1252
{
1253
    return g_strdup(object_get_typename(obj));
1254
}
1255

    
1256
static void object_instance_init(Object *obj)
1257
{
1258
    object_property_add_str(obj, "type", qdev_get_type, NULL, NULL);
1259
}
1260

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

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

    
1276
    type_interface = type_register_internal(&interface_info);
1277
    type_register_internal(&object_info);
1278
}
1279

    
1280
type_init(register_types)