Statistics
| Branch: | Revision:

root / qom / object.c @ 7b7b7d18

History | View | Annotate | Download (25.1 kB)

1 2f28d2ff Anthony Liguori
/*
2 2f28d2ff Anthony Liguori
 * QEMU Object Model
3 2f28d2ff Anthony Liguori
 *
4 2f28d2ff Anthony Liguori
 * Copyright IBM, Corp. 2011
5 2f28d2ff Anthony Liguori
 *
6 2f28d2ff Anthony Liguori
 * Authors:
7 2f28d2ff Anthony Liguori
 *  Anthony Liguori   <aliguori@us.ibm.com>
8 2f28d2ff Anthony Liguori
 *
9 2f28d2ff Anthony Liguori
 * This work is licensed under the terms of the GNU GPL, version 2 or later.
10 2f28d2ff Anthony Liguori
 * See the COPYING file in the top-level directory.
11 2f28d2ff Anthony Liguori
 */
12 2f28d2ff Anthony Liguori
13 2f28d2ff Anthony Liguori
#include "qemu/object.h"
14 2f28d2ff Anthony Liguori
#include "qemu-common.h"
15 57c9fafe Anthony Liguori
#include "qapi/qapi-visit-core.h"
16 2f28d2ff Anthony Liguori
17 7b7b7d18 Paolo Bonzini
/* TODO: replace QObject with a simpler visitor to avoid a dependency
18 7b7b7d18 Paolo Bonzini
 * of the QOM core on QObject?  */
19 7b7b7d18 Paolo Bonzini
#include "qemu/qom-qobject.h"
20 7b7b7d18 Paolo Bonzini
#include "qobject.h"
21 7b7b7d18 Paolo Bonzini
#include "qbool.h"
22 7b7b7d18 Paolo Bonzini
#include "qint.h"
23 7b7b7d18 Paolo Bonzini
#include "qstring.h"
24 7b7b7d18 Paolo Bonzini
25 2f28d2ff Anthony Liguori
#define MAX_INTERFACES 32
26 2f28d2ff Anthony Liguori
27 2f28d2ff Anthony Liguori
typedef struct InterfaceImpl InterfaceImpl;
28 2f28d2ff Anthony Liguori
typedef struct TypeImpl TypeImpl;
29 2f28d2ff Anthony Liguori
30 2f28d2ff Anthony Liguori
struct InterfaceImpl
31 2f28d2ff Anthony Liguori
{
32 2f28d2ff Anthony Liguori
    const char *parent;
33 2f28d2ff Anthony Liguori
    void (*interface_initfn)(ObjectClass *class, void *data);
34 2f28d2ff Anthony Liguori
    TypeImpl *type;
35 2f28d2ff Anthony Liguori
};
36 2f28d2ff Anthony Liguori
37 2f28d2ff Anthony Liguori
struct TypeImpl
38 2f28d2ff Anthony Liguori
{
39 2f28d2ff Anthony Liguori
    const char *name;
40 2f28d2ff Anthony Liguori
41 2f28d2ff Anthony Liguori
    size_t class_size;
42 2f28d2ff Anthony Liguori
43 2f28d2ff Anthony Liguori
    size_t instance_size;
44 2f28d2ff Anthony Liguori
45 2f28d2ff Anthony Liguori
    void (*class_init)(ObjectClass *klass, void *data);
46 2f28d2ff Anthony Liguori
    void (*class_finalize)(ObjectClass *klass, void *data);
47 2f28d2ff Anthony Liguori
48 2f28d2ff Anthony Liguori
    void *class_data;
49 2f28d2ff Anthony Liguori
50 2f28d2ff Anthony Liguori
    void (*instance_init)(Object *obj);
51 2f28d2ff Anthony Liguori
    void (*instance_finalize)(Object *obj);
52 2f28d2ff Anthony Liguori
53 2f28d2ff Anthony Liguori
    bool abstract;
54 2f28d2ff Anthony Liguori
55 2f28d2ff Anthony Liguori
    const char *parent;
56 2f28d2ff Anthony Liguori
    TypeImpl *parent_type;
57 2f28d2ff Anthony Liguori
58 2f28d2ff Anthony Liguori
    ObjectClass *class;
59 2f28d2ff Anthony Liguori
60 2f28d2ff Anthony Liguori
    int num_interfaces;
61 2f28d2ff Anthony Liguori
    InterfaceImpl interfaces[MAX_INTERFACES];
62 2f28d2ff Anthony Liguori
};
63 2f28d2ff Anthony Liguori
64 2f28d2ff Anthony Liguori
typedef struct Interface
65 2f28d2ff Anthony Liguori
{
66 2f28d2ff Anthony Liguori
    Object parent;
67 2f28d2ff Anthony Liguori
    Object *obj;
68 2f28d2ff Anthony Liguori
} Interface;
69 2f28d2ff Anthony Liguori
70 2f28d2ff Anthony Liguori
#define INTERFACE(obj) OBJECT_CHECK(Interface, obj, TYPE_INTERFACE)
71 2f28d2ff Anthony Liguori
72 9970bd88 Paolo Bonzini
static Type type_interface;
73 9970bd88 Paolo Bonzini
74 2f28d2ff Anthony Liguori
static GHashTable *type_table_get(void)
75 2f28d2ff Anthony Liguori
{
76 2f28d2ff Anthony Liguori
    static GHashTable *type_table;
77 2f28d2ff Anthony Liguori
78 2f28d2ff Anthony Liguori
    if (type_table == NULL) {
79 2f28d2ff Anthony Liguori
        type_table = g_hash_table_new(g_str_hash, g_str_equal);
80 2f28d2ff Anthony Liguori
    }
81 2f28d2ff Anthony Liguori
82 2f28d2ff Anthony Liguori
    return type_table;
83 2f28d2ff Anthony Liguori
}
84 2f28d2ff Anthony Liguori
85 2f28d2ff Anthony Liguori
static void type_table_add(TypeImpl *ti)
86 2f28d2ff Anthony Liguori
{
87 2f28d2ff Anthony Liguori
    g_hash_table_insert(type_table_get(), (void *)ti->name, ti);
88 2f28d2ff Anthony Liguori
}
89 2f28d2ff Anthony Liguori
90 2f28d2ff Anthony Liguori
static TypeImpl *type_table_lookup(const char *name)
91 2f28d2ff Anthony Liguori
{
92 2f28d2ff Anthony Liguori
    return g_hash_table_lookup(type_table_get(), name);
93 2f28d2ff Anthony Liguori
}
94 2f28d2ff Anthony Liguori
95 2f28d2ff Anthony Liguori
TypeImpl *type_register(const TypeInfo *info)
96 2f28d2ff Anthony Liguori
{
97 2f28d2ff Anthony Liguori
    TypeImpl *ti = g_malloc0(sizeof(*ti));
98 2f28d2ff Anthony Liguori
99 2f28d2ff Anthony Liguori
    g_assert(info->name != NULL);
100 2f28d2ff Anthony Liguori
101 73093354 Anthony Liguori
    if (type_table_lookup(info->name) != NULL) {
102 73093354 Anthony Liguori
        fprintf(stderr, "Registering `%s' which already exists\n", info->name);
103 73093354 Anthony Liguori
        abort();
104 73093354 Anthony Liguori
    }
105 73093354 Anthony Liguori
106 2f28d2ff Anthony Liguori
    ti->name = g_strdup(info->name);
107 2f28d2ff Anthony Liguori
    ti->parent = g_strdup(info->parent);
108 2f28d2ff Anthony Liguori
109 2f28d2ff Anthony Liguori
    ti->class_size = info->class_size;
110 2f28d2ff Anthony Liguori
    ti->instance_size = info->instance_size;
111 2f28d2ff Anthony Liguori
112 2f28d2ff Anthony Liguori
    ti->class_init = info->class_init;
113 2f28d2ff Anthony Liguori
    ti->class_finalize = info->class_finalize;
114 2f28d2ff Anthony Liguori
    ti->class_data = info->class_data;
115 2f28d2ff Anthony Liguori
116 2f28d2ff Anthony Liguori
    ti->instance_init = info->instance_init;
117 2f28d2ff Anthony Liguori
    ti->instance_finalize = info->instance_finalize;
118 2f28d2ff Anthony Liguori
119 2f28d2ff Anthony Liguori
    ti->abstract = info->abstract;
120 2f28d2ff Anthony Liguori
121 2f28d2ff Anthony Liguori
    if (info->interfaces) {
122 2f28d2ff Anthony Liguori
        int i;
123 2f28d2ff Anthony Liguori
124 2f28d2ff Anthony Liguori
        for (i = 0; info->interfaces[i].type; i++) {
125 2f28d2ff Anthony Liguori
            ti->interfaces[i].parent = info->interfaces[i].type;
126 2f28d2ff Anthony Liguori
            ti->interfaces[i].interface_initfn = info->interfaces[i].interface_initfn;
127 2f28d2ff Anthony Liguori
            ti->num_interfaces++;
128 2f28d2ff Anthony Liguori
        }
129 2f28d2ff Anthony Liguori
    }
130 2f28d2ff Anthony Liguori
131 2f28d2ff Anthony Liguori
    type_table_add(ti);
132 2f28d2ff Anthony Liguori
133 2f28d2ff Anthony Liguori
    return ti;
134 2f28d2ff Anthony Liguori
}
135 2f28d2ff Anthony Liguori
136 2f28d2ff Anthony Liguori
TypeImpl *type_register_static(const TypeInfo *info)
137 2f28d2ff Anthony Liguori
{
138 2f28d2ff Anthony Liguori
    return type_register(info);
139 2f28d2ff Anthony Liguori
}
140 2f28d2ff Anthony Liguori
141 2f28d2ff Anthony Liguori
static TypeImpl *type_get_by_name(const char *name)
142 2f28d2ff Anthony Liguori
{
143 2f28d2ff Anthony Liguori
    if (name == NULL) {
144 2f28d2ff Anthony Liguori
        return NULL;
145 2f28d2ff Anthony Liguori
    }
146 2f28d2ff Anthony Liguori
147 2f28d2ff Anthony Liguori
    return type_table_lookup(name);
148 2f28d2ff Anthony Liguori
}
149 2f28d2ff Anthony Liguori
150 2f28d2ff Anthony Liguori
static TypeImpl *type_get_parent(TypeImpl *type)
151 2f28d2ff Anthony Liguori
{
152 2f28d2ff Anthony Liguori
    if (!type->parent_type && type->parent) {
153 2f28d2ff Anthony Liguori
        type->parent_type = type_get_by_name(type->parent);
154 2f28d2ff Anthony Liguori
        g_assert(type->parent_type != NULL);
155 2f28d2ff Anthony Liguori
    }
156 2f28d2ff Anthony Liguori
157 2f28d2ff Anthony Liguori
    return type->parent_type;
158 2f28d2ff Anthony Liguori
}
159 2f28d2ff Anthony Liguori
160 2f28d2ff Anthony Liguori
static bool type_has_parent(TypeImpl *type)
161 2f28d2ff Anthony Liguori
{
162 2f28d2ff Anthony Liguori
    return (type->parent != NULL);
163 2f28d2ff Anthony Liguori
}
164 2f28d2ff Anthony Liguori
165 2f28d2ff Anthony Liguori
static size_t type_class_get_size(TypeImpl *ti)
166 2f28d2ff Anthony Liguori
{
167 2f28d2ff Anthony Liguori
    if (ti->class_size) {
168 2f28d2ff Anthony Liguori
        return ti->class_size;
169 2f28d2ff Anthony Liguori
    }
170 2f28d2ff Anthony Liguori
171 2f28d2ff Anthony Liguori
    if (type_has_parent(ti)) {
172 2f28d2ff Anthony Liguori
        return type_class_get_size(type_get_parent(ti));
173 2f28d2ff Anthony Liguori
    }
174 2f28d2ff Anthony Liguori
175 2f28d2ff Anthony Liguori
    return sizeof(ObjectClass);
176 2f28d2ff Anthony Liguori
}
177 2f28d2ff Anthony Liguori
178 2f28d2ff Anthony Liguori
static void type_class_interface_init(TypeImpl *ti, InterfaceImpl *iface)
179 2f28d2ff Anthony Liguori
{
180 2f28d2ff Anthony Liguori
    TypeInfo info = {
181 2f28d2ff Anthony Liguori
        .instance_size = sizeof(Interface),
182 2f28d2ff Anthony Liguori
        .parent = iface->parent,
183 2f28d2ff Anthony Liguori
        .class_size = sizeof(InterfaceClass),
184 2f28d2ff Anthony Liguori
        .class_init = iface->interface_initfn,
185 2f28d2ff Anthony Liguori
        .abstract = true,
186 2f28d2ff Anthony Liguori
    };
187 2f28d2ff Anthony Liguori
    char *name = g_strdup_printf("<%s::%s>", ti->name, iface->parent);
188 2f28d2ff Anthony Liguori
189 2f28d2ff Anthony Liguori
    info.name = name;
190 2f28d2ff Anthony Liguori
    iface->type = type_register(&info);
191 2f28d2ff Anthony Liguori
    g_free(name);
192 2f28d2ff Anthony Liguori
}
193 2f28d2ff Anthony Liguori
194 2f28d2ff Anthony Liguori
static void type_class_init(TypeImpl *ti)
195 2f28d2ff Anthony Liguori
{
196 2f28d2ff Anthony Liguori
    size_t class_size = sizeof(ObjectClass);
197 2f28d2ff Anthony Liguori
    int i;
198 2f28d2ff Anthony Liguori
199 2f28d2ff Anthony Liguori
    if (ti->class) {
200 2f28d2ff Anthony Liguori
        return;
201 2f28d2ff Anthony Liguori
    }
202 2f28d2ff Anthony Liguori
203 2f28d2ff Anthony Liguori
    ti->class_size = type_class_get_size(ti);
204 2f28d2ff Anthony Liguori
205 2f28d2ff Anthony Liguori
    ti->class = g_malloc0(ti->class_size);
206 2f28d2ff Anthony Liguori
    ti->class->type = ti;
207 2f28d2ff Anthony Liguori
208 2f28d2ff Anthony Liguori
    if (type_has_parent(ti)) {
209 2f28d2ff Anthony Liguori
        TypeImpl *parent = type_get_parent(ti);
210 2f28d2ff Anthony Liguori
211 2f28d2ff Anthony Liguori
        type_class_init(parent);
212 2f28d2ff Anthony Liguori
213 2f28d2ff Anthony Liguori
        class_size = parent->class_size;
214 2f28d2ff Anthony Liguori
        g_assert(parent->class_size <= ti->class_size);
215 2f28d2ff Anthony Liguori
216 2f28d2ff Anthony Liguori
        memcpy((void *)ti->class + sizeof(ObjectClass),
217 2f28d2ff Anthony Liguori
               (void *)parent->class + sizeof(ObjectClass),
218 2f28d2ff Anthony Liguori
               parent->class_size - sizeof(ObjectClass));
219 2f28d2ff Anthony Liguori
    }
220 2f28d2ff Anthony Liguori
221 2f28d2ff Anthony Liguori
    memset((void *)ti->class + class_size, 0, ti->class_size - class_size);
222 2f28d2ff Anthony Liguori
223 2f28d2ff Anthony Liguori
    for (i = 0; i < ti->num_interfaces; i++) {
224 2f28d2ff Anthony Liguori
        type_class_interface_init(ti, &ti->interfaces[i]);
225 2f28d2ff Anthony Liguori
    }
226 2f28d2ff Anthony Liguori
227 2f28d2ff Anthony Liguori
    if (ti->class_init) {
228 2f28d2ff Anthony Liguori
        ti->class_init(ti->class, ti->class_data);
229 2f28d2ff Anthony Liguori
    }
230 2f28d2ff Anthony Liguori
}
231 2f28d2ff Anthony Liguori
232 2f28d2ff Anthony Liguori
static void object_interface_init(Object *obj, InterfaceImpl *iface)
233 2f28d2ff Anthony Liguori
{
234 2f28d2ff Anthony Liguori
    TypeImpl *ti = iface->type;
235 2f28d2ff Anthony Liguori
    Interface *iface_obj;
236 2f28d2ff Anthony Liguori
237 2f28d2ff Anthony Liguori
    iface_obj = INTERFACE(object_new(ti->name));
238 2f28d2ff Anthony Liguori
    iface_obj->obj = obj;
239 2f28d2ff Anthony Liguori
240 2f28d2ff Anthony Liguori
    obj->interfaces = g_slist_prepend(obj->interfaces, iface_obj);
241 2f28d2ff Anthony Liguori
}
242 2f28d2ff Anthony Liguori
243 2f28d2ff Anthony Liguori
static void object_init_with_type(Object *obj, TypeImpl *ti)
244 2f28d2ff Anthony Liguori
{
245 2f28d2ff Anthony Liguori
    int i;
246 2f28d2ff Anthony Liguori
247 2f28d2ff Anthony Liguori
    if (type_has_parent(ti)) {
248 2f28d2ff Anthony Liguori
        object_init_with_type(obj, type_get_parent(ti));
249 2f28d2ff Anthony Liguori
    }
250 2f28d2ff Anthony Liguori
251 2f28d2ff Anthony Liguori
    for (i = 0; i < ti->num_interfaces; i++) {
252 2f28d2ff Anthony Liguori
        object_interface_init(obj, &ti->interfaces[i]);
253 2f28d2ff Anthony Liguori
    }
254 2f28d2ff Anthony Liguori
255 2f28d2ff Anthony Liguori
    if (ti->instance_init) {
256 2f28d2ff Anthony Liguori
        ti->instance_init(obj);
257 2f28d2ff Anthony Liguori
    }
258 2f28d2ff Anthony Liguori
}
259 2f28d2ff Anthony Liguori
260 2f28d2ff Anthony Liguori
void object_initialize_with_type(void *data, TypeImpl *type)
261 2f28d2ff Anthony Liguori
{
262 2f28d2ff Anthony Liguori
    Object *obj = data;
263 2f28d2ff Anthony Liguori
264 2f28d2ff Anthony Liguori
    g_assert(type != NULL);
265 2f28d2ff Anthony Liguori
    g_assert(type->instance_size >= sizeof(ObjectClass));
266 2f28d2ff Anthony Liguori
267 2f28d2ff Anthony Liguori
    type_class_init(type);
268 2f28d2ff Anthony Liguori
    g_assert(type->abstract == false);
269 2f28d2ff Anthony Liguori
270 2f28d2ff Anthony Liguori
    memset(obj, 0, type->instance_size);
271 2f28d2ff Anthony Liguori
    obj->class = type->class;
272 57c9fafe Anthony Liguori
    QTAILQ_INIT(&obj->properties);
273 2f28d2ff Anthony Liguori
    object_init_with_type(obj, type);
274 2f28d2ff Anthony Liguori
}
275 2f28d2ff Anthony Liguori
276 2f28d2ff Anthony Liguori
void object_initialize(void *data, const char *typename)
277 2f28d2ff Anthony Liguori
{
278 2f28d2ff Anthony Liguori
    TypeImpl *type = type_get_by_name(typename);
279 2f28d2ff Anthony Liguori
280 2f28d2ff Anthony Liguori
    object_initialize_with_type(data, type);
281 2f28d2ff Anthony Liguori
}
282 2f28d2ff Anthony Liguori
283 57c9fafe Anthony Liguori
static void object_property_del_all(Object *obj)
284 57c9fafe Anthony Liguori
{
285 57c9fafe Anthony Liguori
    while (!QTAILQ_EMPTY(&obj->properties)) {
286 57c9fafe Anthony Liguori
        ObjectProperty *prop = QTAILQ_FIRST(&obj->properties);
287 57c9fafe Anthony Liguori
288 57c9fafe Anthony Liguori
        QTAILQ_REMOVE(&obj->properties, prop, node);
289 57c9fafe Anthony Liguori
290 57c9fafe Anthony Liguori
        if (prop->release) {
291 57c9fafe Anthony Liguori
            prop->release(obj, prop->name, prop->opaque);
292 57c9fafe Anthony Liguori
        }
293 57c9fafe Anthony Liguori
294 57c9fafe Anthony Liguori
        g_free(prop->name);
295 57c9fafe Anthony Liguori
        g_free(prop->type);
296 57c9fafe Anthony Liguori
        g_free(prop);
297 57c9fafe Anthony Liguori
    }
298 57c9fafe Anthony Liguori
}
299 57c9fafe Anthony Liguori
300 57c9fafe Anthony Liguori
static void object_property_del_child(Object *obj, Object *child, Error **errp)
301 57c9fafe Anthony Liguori
{
302 57c9fafe Anthony Liguori
    ObjectProperty *prop;
303 57c9fafe Anthony Liguori
304 57c9fafe Anthony Liguori
    QTAILQ_FOREACH(prop, &obj->properties, node) {
305 57c9fafe Anthony Liguori
        if (!strstart(prop->type, "child<", NULL)) {
306 57c9fafe Anthony Liguori
            continue;
307 57c9fafe Anthony Liguori
        }
308 57c9fafe Anthony Liguori
309 57c9fafe Anthony Liguori
        if (prop->opaque == child) {
310 57c9fafe Anthony Liguori
            object_property_del(obj, prop->name, errp);
311 57c9fafe Anthony Liguori
        }
312 57c9fafe Anthony Liguori
    }
313 57c9fafe Anthony Liguori
}
314 57c9fafe Anthony Liguori
315 57c9fafe Anthony Liguori
void object_unparent(Object *obj)
316 57c9fafe Anthony Liguori
{
317 57c9fafe Anthony Liguori
    if (obj->parent) {
318 57c9fafe Anthony Liguori
        object_property_del_child(obj->parent, obj, NULL);
319 57c9fafe Anthony Liguori
    }
320 57c9fafe Anthony Liguori
}
321 57c9fafe Anthony Liguori
322 2f28d2ff Anthony Liguori
static void object_deinit(Object *obj, TypeImpl *type)
323 2f28d2ff Anthony Liguori
{
324 2f28d2ff Anthony Liguori
    if (type->instance_finalize) {
325 2f28d2ff Anthony Liguori
        type->instance_finalize(obj);
326 2f28d2ff Anthony Liguori
    }
327 2f28d2ff Anthony Liguori
328 2f28d2ff Anthony Liguori
    while (obj->interfaces) {
329 2f28d2ff Anthony Liguori
        Interface *iface_obj = obj->interfaces->data;
330 2f28d2ff Anthony Liguori
        obj->interfaces = g_slist_delete_link(obj->interfaces, obj->interfaces);
331 2f28d2ff Anthony Liguori
        object_delete(OBJECT(iface_obj));
332 2f28d2ff Anthony Liguori
    }
333 2f28d2ff Anthony Liguori
334 2f28d2ff Anthony Liguori
    if (type_has_parent(type)) {
335 2f28d2ff Anthony Liguori
        object_deinit(obj, type_get_parent(type));
336 2f28d2ff Anthony Liguori
    }
337 57c9fafe Anthony Liguori
338 57c9fafe Anthony Liguori
    object_unparent(obj);
339 2f28d2ff Anthony Liguori
}
340 2f28d2ff Anthony Liguori
341 2f28d2ff Anthony Liguori
void object_finalize(void *data)
342 2f28d2ff Anthony Liguori
{
343 2f28d2ff Anthony Liguori
    Object *obj = data;
344 2f28d2ff Anthony Liguori
    TypeImpl *ti = obj->class->type;
345 2f28d2ff Anthony Liguori
346 2f28d2ff Anthony Liguori
    object_deinit(obj, ti);
347 57c9fafe Anthony Liguori
    object_property_del_all(obj);
348 db85b575 Anthony Liguori
349 db85b575 Anthony Liguori
    g_assert(obj->ref == 0);
350 2f28d2ff Anthony Liguori
}
351 2f28d2ff Anthony Liguori
352 2f28d2ff Anthony Liguori
Object *object_new_with_type(Type type)
353 2f28d2ff Anthony Liguori
{
354 2f28d2ff Anthony Liguori
    Object *obj;
355 2f28d2ff Anthony Liguori
356 2f28d2ff Anthony Liguori
    g_assert(type != NULL);
357 2f28d2ff Anthony Liguori
358 2f28d2ff Anthony Liguori
    obj = g_malloc(type->instance_size);
359 2f28d2ff Anthony Liguori
    object_initialize_with_type(obj, type);
360 db85b575 Anthony Liguori
    object_ref(obj);
361 2f28d2ff Anthony Liguori
362 2f28d2ff Anthony Liguori
    return obj;
363 2f28d2ff Anthony Liguori
}
364 2f28d2ff Anthony Liguori
365 2f28d2ff Anthony Liguori
Object *object_new(const char *typename)
366 2f28d2ff Anthony Liguori
{
367 2f28d2ff Anthony Liguori
    TypeImpl *ti = type_get_by_name(typename);
368 2f28d2ff Anthony Liguori
369 2f28d2ff Anthony Liguori
    return object_new_with_type(ti);
370 2f28d2ff Anthony Liguori
}
371 2f28d2ff Anthony Liguori
372 2f28d2ff Anthony Liguori
void object_delete(Object *obj)
373 2f28d2ff Anthony Liguori
{
374 db85b575 Anthony Liguori
    object_unref(obj);
375 db85b575 Anthony Liguori
    g_assert(obj->ref == 0);
376 2f28d2ff Anthony Liguori
    g_free(obj);
377 2f28d2ff Anthony Liguori
}
378 2f28d2ff Anthony Liguori
379 acc4af3f Paolo Bonzini
static bool type_is_ancestor(TypeImpl *type, TypeImpl *target_type)
380 2f28d2ff Anthony Liguori
{
381 acc4af3f Paolo Bonzini
    assert(target_type);
382 2f28d2ff Anthony Liguori
383 2f28d2ff Anthony Liguori
    /* Check if typename is a direct ancestor of type */
384 2f28d2ff Anthony Liguori
    while (type) {
385 2f28d2ff Anthony Liguori
        if (type == target_type) {
386 2f28d2ff Anthony Liguori
            return true;
387 2f28d2ff Anthony Liguori
        }
388 2f28d2ff Anthony Liguori
389 2f28d2ff Anthony Liguori
        type = type_get_parent(type);
390 2f28d2ff Anthony Liguori
    }
391 2f28d2ff Anthony Liguori
392 acc4af3f Paolo Bonzini
    return false;
393 acc4af3f Paolo Bonzini
}
394 2f28d2ff Anthony Liguori
395 9970bd88 Paolo Bonzini
static bool object_is_type(Object *obj, TypeImpl *target_type)
396 acc4af3f Paolo Bonzini
{
397 9970bd88 Paolo Bonzini
    return !target_type || type_is_ancestor(obj->class->type, target_type);
398 2f28d2ff Anthony Liguori
}
399 2f28d2ff Anthony Liguori
400 2f28d2ff Anthony Liguori
Object *object_dynamic_cast(Object *obj, const char *typename)
401 2f28d2ff Anthony Liguori
{
402 9970bd88 Paolo Bonzini
    TypeImpl *target_type = type_get_by_name(typename);
403 2f28d2ff Anthony Liguori
    GSList *i;
404 2f28d2ff Anthony Liguori
405 acc4af3f Paolo Bonzini
    /* Check if typename is a direct ancestor.  Special-case TYPE_OBJECT,
406 acc4af3f Paolo Bonzini
     * we want to go back from interfaces to the parent.
407 acc4af3f Paolo Bonzini
    */
408 9970bd88 Paolo Bonzini
    if (target_type && object_is_type(obj, target_type)) {
409 acc4af3f Paolo Bonzini
        return obj;
410 acc4af3f Paolo Bonzini
    }
411 acc4af3f Paolo Bonzini
412 acc4af3f Paolo Bonzini
    /* Check if obj is an interface and its containing object is a direct
413 acc4af3f Paolo Bonzini
     * ancestor of typename.  In principle we could do this test at the very
414 acc4af3f Paolo Bonzini
     * beginning of object_dynamic_cast, avoiding a second call to
415 acc4af3f Paolo Bonzini
     * object_is_type.  However, casting between interfaces is relatively
416 9970bd88 Paolo Bonzini
     * rare, and object_is_type(obj, type_interface) would fail almost always.
417 acc4af3f Paolo Bonzini
     *
418 acc4af3f Paolo Bonzini
     * Perhaps we could add a magic value to the object header for increased
419 acc4af3f Paolo Bonzini
     * (run-time) type safety and to speed up tests like this one.  If we ever
420 acc4af3f Paolo Bonzini
     * do that we can revisit the order here.
421 acc4af3f Paolo Bonzini
     */
422 9970bd88 Paolo Bonzini
    if (object_is_type(obj, type_interface)) {
423 acc4af3f Paolo Bonzini
        assert(!obj->interfaces);
424 acc4af3f Paolo Bonzini
        obj = INTERFACE(obj)->obj;
425 9970bd88 Paolo Bonzini
        if (object_is_type(obj, target_type)) {
426 acc4af3f Paolo Bonzini
            return obj;
427 acc4af3f Paolo Bonzini
        }
428 acc4af3f Paolo Bonzini
    }
429 acc4af3f Paolo Bonzini
430 9970bd88 Paolo Bonzini
    if (!target_type) {
431 2f28d2ff Anthony Liguori
        return obj;
432 2f28d2ff Anthony Liguori
    }
433 2f28d2ff Anthony Liguori
434 2f28d2ff Anthony Liguori
    /* Check if obj has an interface of typename */
435 2f28d2ff Anthony Liguori
    for (i = obj->interfaces; i; i = i->next) {
436 2f28d2ff Anthony Liguori
        Interface *iface = i->data;
437 2f28d2ff Anthony Liguori
438 9970bd88 Paolo Bonzini
        if (object_is_type(OBJECT(iface), target_type)) {
439 2f28d2ff Anthony Liguori
            return OBJECT(iface);
440 2f28d2ff Anthony Liguori
        }
441 2f28d2ff Anthony Liguori
    }
442 2f28d2ff Anthony Liguori
443 2f28d2ff Anthony Liguori
    return NULL;
444 2f28d2ff Anthony Liguori
}
445 2f28d2ff Anthony Liguori
446 2f28d2ff Anthony Liguori
447 2f28d2ff Anthony Liguori
static void register_interface(void)
448 2f28d2ff Anthony Liguori
{
449 2f28d2ff Anthony Liguori
    static TypeInfo interface_info = {
450 2f28d2ff Anthony Liguori
        .name = TYPE_INTERFACE,
451 2f28d2ff Anthony Liguori
        .instance_size = sizeof(Interface),
452 2f28d2ff Anthony Liguori
        .abstract = true,
453 2f28d2ff Anthony Liguori
    };
454 2f28d2ff Anthony Liguori
455 9970bd88 Paolo Bonzini
    type_interface = type_register_static(&interface_info);
456 2f28d2ff Anthony Liguori
}
457 2f28d2ff Anthony Liguori
458 2f28d2ff Anthony Liguori
device_init(register_interface);
459 2f28d2ff Anthony Liguori
460 2f28d2ff Anthony Liguori
Object *object_dynamic_cast_assert(Object *obj, const char *typename)
461 2f28d2ff Anthony Liguori
{
462 2f28d2ff Anthony Liguori
    Object *inst;
463 2f28d2ff Anthony Liguori
464 2f28d2ff Anthony Liguori
    inst = object_dynamic_cast(obj, typename);
465 2f28d2ff Anthony Liguori
466 2f28d2ff Anthony Liguori
    if (!inst) {
467 2f28d2ff Anthony Liguori
        fprintf(stderr, "Object %p is not an instance of type %s\n",
468 2f28d2ff Anthony Liguori
                obj, typename);
469 2f28d2ff Anthony Liguori
        abort();
470 2f28d2ff Anthony Liguori
    }
471 2f28d2ff Anthony Liguori
472 2f28d2ff Anthony Liguori
    return inst;
473 2f28d2ff Anthony Liguori
}
474 2f28d2ff Anthony Liguori
475 2f28d2ff Anthony Liguori
ObjectClass *object_class_dynamic_cast(ObjectClass *class,
476 2f28d2ff Anthony Liguori
                                       const char *typename)
477 2f28d2ff Anthony Liguori
{
478 2f28d2ff Anthony Liguori
    TypeImpl *target_type = type_get_by_name(typename);
479 2f28d2ff Anthony Liguori
    TypeImpl *type = class->type;
480 2f28d2ff Anthony Liguori
481 2f28d2ff Anthony Liguori
    while (type) {
482 2f28d2ff Anthony Liguori
        if (type == target_type) {
483 2f28d2ff Anthony Liguori
            return class;
484 2f28d2ff Anthony Liguori
        }
485 2f28d2ff Anthony Liguori
486 2f28d2ff Anthony Liguori
        type = type_get_parent(type);
487 2f28d2ff Anthony Liguori
    }
488 2f28d2ff Anthony Liguori
489 2f28d2ff Anthony Liguori
    return NULL;
490 2f28d2ff Anthony Liguori
}
491 2f28d2ff Anthony Liguori
492 2f28d2ff Anthony Liguori
ObjectClass *object_class_dynamic_cast_assert(ObjectClass *class,
493 2f28d2ff Anthony Liguori
                                              const char *typename)
494 2f28d2ff Anthony Liguori
{
495 2f28d2ff Anthony Liguori
    ObjectClass *ret = object_class_dynamic_cast(class, typename);
496 2f28d2ff Anthony Liguori
497 2f28d2ff Anthony Liguori
    if (!ret) {
498 2f28d2ff Anthony Liguori
        fprintf(stderr, "Object %p is not an instance of type %s\n",
499 2f28d2ff Anthony Liguori
                class, typename);
500 2f28d2ff Anthony Liguori
        abort();
501 2f28d2ff Anthony Liguori
    }
502 2f28d2ff Anthony Liguori
503 2f28d2ff Anthony Liguori
    return ret;
504 2f28d2ff Anthony Liguori
}
505 2f28d2ff Anthony Liguori
506 2f28d2ff Anthony Liguori
const char *object_get_typename(Object *obj)
507 2f28d2ff Anthony Liguori
{
508 2f28d2ff Anthony Liguori
    return obj->class->type->name;
509 2f28d2ff Anthony Liguori
}
510 2f28d2ff Anthony Liguori
511 2f28d2ff Anthony Liguori
ObjectClass *object_get_class(Object *obj)
512 2f28d2ff Anthony Liguori
{
513 2f28d2ff Anthony Liguori
    return obj->class;
514 2f28d2ff Anthony Liguori
}
515 2f28d2ff Anthony Liguori
516 2f28d2ff Anthony Liguori
const char *object_class_get_name(ObjectClass *klass)
517 2f28d2ff Anthony Liguori
{
518 2f28d2ff Anthony Liguori
    return klass->type->name;
519 2f28d2ff Anthony Liguori
}
520 2f28d2ff Anthony Liguori
521 2f28d2ff Anthony Liguori
ObjectClass *object_class_by_name(const char *typename)
522 2f28d2ff Anthony Liguori
{
523 2f28d2ff Anthony Liguori
    TypeImpl *type = type_get_by_name(typename);
524 2f28d2ff Anthony Liguori
525 2f28d2ff Anthony Liguori
    if (!type) {
526 2f28d2ff Anthony Liguori
        return NULL;
527 2f28d2ff Anthony Liguori
    }
528 2f28d2ff Anthony Liguori
529 2f28d2ff Anthony Liguori
    type_class_init(type);
530 2f28d2ff Anthony Liguori
531 2f28d2ff Anthony Liguori
    return type->class;
532 2f28d2ff Anthony Liguori
}
533 2f28d2ff Anthony Liguori
534 2f28d2ff Anthony Liguori
typedef struct OCFData
535 2f28d2ff Anthony Liguori
{
536 2f28d2ff Anthony Liguori
    void (*fn)(ObjectClass *klass, void *opaque);
537 93c511a1 Anthony Liguori
    const char *implements_type;
538 93c511a1 Anthony Liguori
    bool include_abstract;
539 2f28d2ff Anthony Liguori
    void *opaque;
540 2f28d2ff Anthony Liguori
} OCFData;
541 2f28d2ff Anthony Liguori
542 2f28d2ff Anthony Liguori
static void object_class_foreach_tramp(gpointer key, gpointer value,
543 2f28d2ff Anthony Liguori
                                       gpointer opaque)
544 2f28d2ff Anthony Liguori
{
545 2f28d2ff Anthony Liguori
    OCFData *data = opaque;
546 2f28d2ff Anthony Liguori
    TypeImpl *type = value;
547 93c511a1 Anthony Liguori
    ObjectClass *k;
548 2f28d2ff Anthony Liguori
549 2f28d2ff Anthony Liguori
    type_class_init(type);
550 93c511a1 Anthony Liguori
    k = type->class;
551 2f28d2ff Anthony Liguori
552 93c511a1 Anthony Liguori
    if (!data->include_abstract && type->abstract) {
553 93c511a1 Anthony Liguori
        return;
554 93c511a1 Anthony Liguori
    }
555 93c511a1 Anthony Liguori
556 93c511a1 Anthony Liguori
    if (data->implements_type && 
557 93c511a1 Anthony Liguori
        !object_class_dynamic_cast(k, data->implements_type)) {
558 93c511a1 Anthony Liguori
        return;
559 93c511a1 Anthony Liguori
    }
560 93c511a1 Anthony Liguori
561 93c511a1 Anthony Liguori
    data->fn(k, data->opaque);
562 2f28d2ff Anthony Liguori
}
563 2f28d2ff Anthony Liguori
564 2f28d2ff Anthony Liguori
void object_class_foreach(void (*fn)(ObjectClass *klass, void *opaque),
565 93c511a1 Anthony Liguori
                          const char *implements_type, bool include_abstract,
566 2f28d2ff Anthony Liguori
                          void *opaque)
567 2f28d2ff Anthony Liguori
{
568 93c511a1 Anthony Liguori
    OCFData data = { fn, implements_type, include_abstract, opaque };
569 2f28d2ff Anthony Liguori
570 2f28d2ff Anthony Liguori
    g_hash_table_foreach(type_table_get(), object_class_foreach_tramp, &data);
571 2f28d2ff Anthony Liguori
}
572 57c9fafe Anthony Liguori
573 57c9fafe Anthony Liguori
void object_ref(Object *obj)
574 57c9fafe Anthony Liguori
{
575 57c9fafe Anthony Liguori
    obj->ref++;
576 57c9fafe Anthony Liguori
}
577 57c9fafe Anthony Liguori
578 57c9fafe Anthony Liguori
void object_unref(Object *obj)
579 57c9fafe Anthony Liguori
{
580 57c9fafe Anthony Liguori
    g_assert(obj->ref > 0);
581 57c9fafe Anthony Liguori
    obj->ref--;
582 57c9fafe Anthony Liguori
583 57c9fafe Anthony Liguori
    /* parent always holds a reference to its children */
584 57c9fafe Anthony Liguori
    if (obj->ref == 0) {
585 57c9fafe Anthony Liguori
        object_finalize(obj);
586 57c9fafe Anthony Liguori
    }
587 57c9fafe Anthony Liguori
}
588 57c9fafe Anthony Liguori
589 57c9fafe Anthony Liguori
void object_property_add(Object *obj, const char *name, const char *type,
590 57c9fafe Anthony Liguori
                         ObjectPropertyAccessor *get,
591 57c9fafe Anthony Liguori
                         ObjectPropertyAccessor *set,
592 57c9fafe Anthony Liguori
                         ObjectPropertyRelease *release,
593 57c9fafe Anthony Liguori
                         void *opaque, Error **errp)
594 57c9fafe Anthony Liguori
{
595 57c9fafe Anthony Liguori
    ObjectProperty *prop = g_malloc0(sizeof(*prop));
596 57c9fafe Anthony Liguori
597 57c9fafe Anthony Liguori
    prop->name = g_strdup(name);
598 57c9fafe Anthony Liguori
    prop->type = g_strdup(type);
599 57c9fafe Anthony Liguori
600 57c9fafe Anthony Liguori
    prop->get = get;
601 57c9fafe Anthony Liguori
    prop->set = set;
602 57c9fafe Anthony Liguori
    prop->release = release;
603 57c9fafe Anthony Liguori
    prop->opaque = opaque;
604 57c9fafe Anthony Liguori
605 57c9fafe Anthony Liguori
    QTAILQ_INSERT_TAIL(&obj->properties, prop, node);
606 57c9fafe Anthony Liguori
}
607 57c9fafe Anthony Liguori
608 57c9fafe Anthony Liguori
static ObjectProperty *object_property_find(Object *obj, const char *name)
609 57c9fafe Anthony Liguori
{
610 57c9fafe Anthony Liguori
    ObjectProperty *prop;
611 57c9fafe Anthony Liguori
612 57c9fafe Anthony Liguori
    QTAILQ_FOREACH(prop, &obj->properties, node) {
613 57c9fafe Anthony Liguori
        if (strcmp(prop->name, name) == 0) {
614 57c9fafe Anthony Liguori
            return prop;
615 57c9fafe Anthony Liguori
        }
616 57c9fafe Anthony Liguori
    }
617 57c9fafe Anthony Liguori
618 57c9fafe Anthony Liguori
    return NULL;
619 57c9fafe Anthony Liguori
}
620 57c9fafe Anthony Liguori
621 57c9fafe Anthony Liguori
void object_property_del(Object *obj, const char *name, Error **errp)
622 57c9fafe Anthony Liguori
{
623 57c9fafe Anthony Liguori
    ObjectProperty *prop = object_property_find(obj, name);
624 57c9fafe Anthony Liguori
625 57c9fafe Anthony Liguori
    QTAILQ_REMOVE(&obj->properties, prop, node);
626 57c9fafe Anthony Liguori
627 57c9fafe Anthony Liguori
    prop->release(obj, prop->name, prop->opaque);
628 57c9fafe Anthony Liguori
629 57c9fafe Anthony Liguori
    g_free(prop->name);
630 57c9fafe Anthony Liguori
    g_free(prop->type);
631 57c9fafe Anthony Liguori
    g_free(prop);
632 57c9fafe Anthony Liguori
}
633 57c9fafe Anthony Liguori
634 57c9fafe Anthony Liguori
void object_property_get(Object *obj, Visitor *v, const char *name,
635 57c9fafe Anthony Liguori
                         Error **errp)
636 57c9fafe Anthony Liguori
{
637 57c9fafe Anthony Liguori
    ObjectProperty *prop = object_property_find(obj, name);
638 57c9fafe Anthony Liguori
639 57c9fafe Anthony Liguori
    if (prop == NULL) {
640 57c9fafe Anthony Liguori
        error_set(errp, QERR_PROPERTY_NOT_FOUND, "", name);
641 57c9fafe Anthony Liguori
        return;
642 57c9fafe Anthony Liguori
    }
643 57c9fafe Anthony Liguori
644 57c9fafe Anthony Liguori
    if (!prop->get) {
645 57c9fafe Anthony Liguori
        error_set(errp, QERR_PERMISSION_DENIED);
646 57c9fafe Anthony Liguori
    } else {
647 57c9fafe Anthony Liguori
        prop->get(obj, v, prop->opaque, name, errp);
648 57c9fafe Anthony Liguori
    }
649 57c9fafe Anthony Liguori
}
650 57c9fafe Anthony Liguori
651 57c9fafe Anthony Liguori
void object_property_set(Object *obj, Visitor *v, const char *name,
652 57c9fafe Anthony Liguori
                         Error **errp)
653 57c9fafe Anthony Liguori
{
654 57c9fafe Anthony Liguori
    ObjectProperty *prop = object_property_find(obj, name);
655 57c9fafe Anthony Liguori
656 57c9fafe Anthony Liguori
    if (prop == NULL) {
657 57c9fafe Anthony Liguori
        error_set(errp, QERR_PROPERTY_NOT_FOUND, "", name);
658 57c9fafe Anthony Liguori
        return;
659 57c9fafe Anthony Liguori
    }
660 57c9fafe Anthony Liguori
661 57c9fafe Anthony Liguori
    if (!prop->set) {
662 57c9fafe Anthony Liguori
        error_set(errp, QERR_PERMISSION_DENIED);
663 57c9fafe Anthony Liguori
    } else {
664 57c9fafe Anthony Liguori
        prop->set(obj, v, prop->opaque, name, errp);
665 57c9fafe Anthony Liguori
    }
666 57c9fafe Anthony Liguori
}
667 57c9fafe Anthony Liguori
668 7b7b7d18 Paolo Bonzini
void object_property_set_str(Object *obj, const char *value,
669 7b7b7d18 Paolo Bonzini
                             const char *name, Error **errp)
670 7b7b7d18 Paolo Bonzini
{
671 7b7b7d18 Paolo Bonzini
    QString *qstr = qstring_from_str(value);
672 7b7b7d18 Paolo Bonzini
    object_property_set_qobject(obj, QOBJECT(qstr), name, errp);
673 7b7b7d18 Paolo Bonzini
674 7b7b7d18 Paolo Bonzini
    QDECREF(qstr);
675 7b7b7d18 Paolo Bonzini
}
676 7b7b7d18 Paolo Bonzini
677 7b7b7d18 Paolo Bonzini
char *object_property_get_str(Object *obj, const char *name,
678 7b7b7d18 Paolo Bonzini
                              Error **errp)
679 7b7b7d18 Paolo Bonzini
{
680 7b7b7d18 Paolo Bonzini
    QObject *ret = object_property_get_qobject(obj, name, errp);
681 7b7b7d18 Paolo Bonzini
    QString *qstring;
682 7b7b7d18 Paolo Bonzini
    char *retval;
683 7b7b7d18 Paolo Bonzini
684 7b7b7d18 Paolo Bonzini
    if (!ret) {
685 7b7b7d18 Paolo Bonzini
        return NULL;
686 7b7b7d18 Paolo Bonzini
    }
687 7b7b7d18 Paolo Bonzini
    qstring = qobject_to_qstring(ret);
688 7b7b7d18 Paolo Bonzini
    if (!qstring) {
689 7b7b7d18 Paolo Bonzini
        error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, "string");
690 7b7b7d18 Paolo Bonzini
        retval = NULL;
691 7b7b7d18 Paolo Bonzini
    } else {
692 7b7b7d18 Paolo Bonzini
        retval = g_strdup(qstring_get_str(qstring));
693 7b7b7d18 Paolo Bonzini
    }
694 7b7b7d18 Paolo Bonzini
695 7b7b7d18 Paolo Bonzini
    QDECREF(qstring);
696 7b7b7d18 Paolo Bonzini
    return retval;
697 7b7b7d18 Paolo Bonzini
}
698 7b7b7d18 Paolo Bonzini
699 7b7b7d18 Paolo Bonzini
void object_property_set_bool(Object *obj, bool value,
700 7b7b7d18 Paolo Bonzini
                              const char *name, Error **errp)
701 7b7b7d18 Paolo Bonzini
{
702 7b7b7d18 Paolo Bonzini
    QBool *qbool = qbool_from_int(value);
703 7b7b7d18 Paolo Bonzini
    object_property_set_qobject(obj, QOBJECT(qbool), name, errp);
704 7b7b7d18 Paolo Bonzini
705 7b7b7d18 Paolo Bonzini
    QDECREF(qbool);
706 7b7b7d18 Paolo Bonzini
}
707 7b7b7d18 Paolo Bonzini
708 7b7b7d18 Paolo Bonzini
bool object_property_get_bool(Object *obj, const char *name,
709 7b7b7d18 Paolo Bonzini
                              Error **errp)
710 7b7b7d18 Paolo Bonzini
{
711 7b7b7d18 Paolo Bonzini
    QObject *ret = object_property_get_qobject(obj, name, errp);
712 7b7b7d18 Paolo Bonzini
    QBool *qbool;
713 7b7b7d18 Paolo Bonzini
    bool retval;
714 7b7b7d18 Paolo Bonzini
715 7b7b7d18 Paolo Bonzini
    if (!ret) {
716 7b7b7d18 Paolo Bonzini
        return false;
717 7b7b7d18 Paolo Bonzini
    }
718 7b7b7d18 Paolo Bonzini
    qbool = qobject_to_qbool(ret);
719 7b7b7d18 Paolo Bonzini
    if (!qbool) {
720 7b7b7d18 Paolo Bonzini
        error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, "boolean");
721 7b7b7d18 Paolo Bonzini
        retval = false;
722 7b7b7d18 Paolo Bonzini
    } else {
723 7b7b7d18 Paolo Bonzini
        retval = qbool_get_int(qbool);
724 7b7b7d18 Paolo Bonzini
    }
725 7b7b7d18 Paolo Bonzini
726 7b7b7d18 Paolo Bonzini
    QDECREF(qbool);
727 7b7b7d18 Paolo Bonzini
    return retval;
728 7b7b7d18 Paolo Bonzini
}
729 7b7b7d18 Paolo Bonzini
730 7b7b7d18 Paolo Bonzini
void object_property_set_int(Object *obj, int64_t value,
731 7b7b7d18 Paolo Bonzini
                             const char *name, Error **errp)
732 7b7b7d18 Paolo Bonzini
{
733 7b7b7d18 Paolo Bonzini
    QInt *qint = qint_from_int(value);
734 7b7b7d18 Paolo Bonzini
    object_property_set_qobject(obj, QOBJECT(qint), name, errp);
735 7b7b7d18 Paolo Bonzini
736 7b7b7d18 Paolo Bonzini
    QDECREF(qint);
737 7b7b7d18 Paolo Bonzini
}
738 7b7b7d18 Paolo Bonzini
739 7b7b7d18 Paolo Bonzini
int64_t object_property_get_int(Object *obj, const char *name,
740 7b7b7d18 Paolo Bonzini
                                Error **errp)
741 7b7b7d18 Paolo Bonzini
{
742 7b7b7d18 Paolo Bonzini
    QObject *ret = object_property_get_qobject(obj, name, errp);
743 7b7b7d18 Paolo Bonzini
    QInt *qint;
744 7b7b7d18 Paolo Bonzini
    int64_t retval;
745 7b7b7d18 Paolo Bonzini
746 7b7b7d18 Paolo Bonzini
    if (!ret) {
747 7b7b7d18 Paolo Bonzini
        return -1;
748 7b7b7d18 Paolo Bonzini
    }
749 7b7b7d18 Paolo Bonzini
    qint = qobject_to_qint(ret);
750 7b7b7d18 Paolo Bonzini
    if (!qint) {
751 7b7b7d18 Paolo Bonzini
        error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, "int");
752 7b7b7d18 Paolo Bonzini
        retval = -1;
753 7b7b7d18 Paolo Bonzini
    } else {
754 7b7b7d18 Paolo Bonzini
        retval = qint_get_int(qint);
755 7b7b7d18 Paolo Bonzini
    }
756 7b7b7d18 Paolo Bonzini
757 7b7b7d18 Paolo Bonzini
    QDECREF(qint);
758 7b7b7d18 Paolo Bonzini
    return retval;
759 7b7b7d18 Paolo Bonzini
}
760 7b7b7d18 Paolo Bonzini
761 57c9fafe Anthony Liguori
const char *object_property_get_type(Object *obj, const char *name, Error **errp)
762 57c9fafe Anthony Liguori
{
763 57c9fafe Anthony Liguori
    ObjectProperty *prop = object_property_find(obj, name);
764 57c9fafe Anthony Liguori
765 57c9fafe Anthony Liguori
    if (prop == NULL) {
766 57c9fafe Anthony Liguori
        error_set(errp, QERR_PROPERTY_NOT_FOUND, "", name);
767 57c9fafe Anthony Liguori
        return NULL;
768 57c9fafe Anthony Liguori
    }
769 57c9fafe Anthony Liguori
770 57c9fafe Anthony Liguori
    return prop->type;
771 57c9fafe Anthony Liguori
}
772 57c9fafe Anthony Liguori
773 57c9fafe Anthony Liguori
Object *object_get_root(void)
774 57c9fafe Anthony Liguori
{
775 8b45d447 Anthony Liguori
    static Object *root;
776 57c9fafe Anthony Liguori
777 8b45d447 Anthony Liguori
    if (!root) {
778 8b45d447 Anthony Liguori
        root = object_new("container");
779 57c9fafe Anthony Liguori
    }
780 57c9fafe Anthony Liguori
781 8b45d447 Anthony Liguori
    return root;
782 57c9fafe Anthony Liguori
}
783 57c9fafe Anthony Liguori
784 57c9fafe Anthony Liguori
static void object_get_child_property(Object *obj, Visitor *v, void *opaque,
785 57c9fafe Anthony Liguori
                                      const char *name, Error **errp)
786 57c9fafe Anthony Liguori
{
787 57c9fafe Anthony Liguori
    Object *child = opaque;
788 57c9fafe Anthony Liguori
    gchar *path;
789 57c9fafe Anthony Liguori
790 57c9fafe Anthony Liguori
    path = object_get_canonical_path(child);
791 57c9fafe Anthony Liguori
    visit_type_str(v, &path, name, errp);
792 57c9fafe Anthony Liguori
    g_free(path);
793 57c9fafe Anthony Liguori
}
794 57c9fafe Anthony Liguori
795 db85b575 Anthony Liguori
static void object_finalize_child_property(Object *obj, const char *name,
796 db85b575 Anthony Liguori
                                           void *opaque)
797 db85b575 Anthony Liguori
{
798 db85b575 Anthony Liguori
    Object *child = opaque;
799 db85b575 Anthony Liguori
800 db85b575 Anthony Liguori
    object_unref(child);
801 db85b575 Anthony Liguori
}
802 db85b575 Anthony Liguori
803 57c9fafe Anthony Liguori
void object_property_add_child(Object *obj, const char *name,
804 57c9fafe Anthony Liguori
                               Object *child, Error **errp)
805 57c9fafe Anthony Liguori
{
806 57c9fafe Anthony Liguori
    gchar *type;
807 57c9fafe Anthony Liguori
808 57c9fafe Anthony Liguori
    type = g_strdup_printf("child<%s>", object_get_typename(OBJECT(child)));
809 57c9fafe Anthony Liguori
810 57c9fafe Anthony Liguori
    object_property_add(obj, name, type, object_get_child_property,
811 db85b575 Anthony Liguori
                        NULL, object_finalize_child_property, child, errp);
812 57c9fafe Anthony Liguori
813 57c9fafe Anthony Liguori
    object_ref(child);
814 57c9fafe Anthony Liguori
    g_assert(child->parent == NULL);
815 57c9fafe Anthony Liguori
    child->parent = obj;
816 57c9fafe Anthony Liguori
817 57c9fafe Anthony Liguori
    g_free(type);
818 57c9fafe Anthony Liguori
}
819 57c9fafe Anthony Liguori
820 57c9fafe Anthony Liguori
static void object_get_link_property(Object *obj, Visitor *v, void *opaque,
821 57c9fafe Anthony Liguori
                                     const char *name, Error **errp)
822 57c9fafe Anthony Liguori
{
823 57c9fafe Anthony Liguori
    Object **child = opaque;
824 57c9fafe Anthony Liguori
    gchar *path;
825 57c9fafe Anthony Liguori
826 57c9fafe Anthony Liguori
    if (*child) {
827 57c9fafe Anthony Liguori
        path = object_get_canonical_path(*child);
828 57c9fafe Anthony Liguori
        visit_type_str(v, &path, name, errp);
829 57c9fafe Anthony Liguori
        g_free(path);
830 57c9fafe Anthony Liguori
    } else {
831 57c9fafe Anthony Liguori
        path = (gchar *)"";
832 57c9fafe Anthony Liguori
        visit_type_str(v, &path, name, errp);
833 57c9fafe Anthony Liguori
    }
834 57c9fafe Anthony Liguori
}
835 57c9fafe Anthony Liguori
836 57c9fafe Anthony Liguori
static void object_set_link_property(Object *obj, Visitor *v, void *opaque,
837 57c9fafe Anthony Liguori
                                     const char *name, Error **errp)
838 57c9fafe Anthony Liguori
{
839 57c9fafe Anthony Liguori
    Object **child = opaque;
840 57c9fafe Anthony Liguori
    bool ambiguous = false;
841 57c9fafe Anthony Liguori
    const char *type;
842 57c9fafe Anthony Liguori
    char *path;
843 57c9fafe Anthony Liguori
844 57c9fafe Anthony Liguori
    type = object_property_get_type(obj, name, NULL);
845 57c9fafe Anthony Liguori
846 57c9fafe Anthony Liguori
    visit_type_str(v, &path, name, errp);
847 57c9fafe Anthony Liguori
848 57c9fafe Anthony Liguori
    if (*child) {
849 57c9fafe Anthony Liguori
        object_unref(*child);
850 57c9fafe Anthony Liguori
    }
851 57c9fafe Anthony Liguori
852 57c9fafe Anthony Liguori
    if (strcmp(path, "") != 0) {
853 57c9fafe Anthony Liguori
        Object *target;
854 57c9fafe Anthony Liguori
855 57c9fafe Anthony Liguori
        target = object_resolve_path(path, &ambiguous);
856 57c9fafe Anthony Liguori
        if (target) {
857 57c9fafe Anthony Liguori
            gchar *target_type;
858 57c9fafe Anthony Liguori
859 fe40e627 Anthony Liguori
            target_type = g_strdup(&type[5]);
860 fe40e627 Anthony Liguori
            target_type[strlen(target_type) - 2] = 0;
861 fe40e627 Anthony Liguori
862 fe40e627 Anthony Liguori
            if (object_dynamic_cast(target, target_type)) {
863 57c9fafe Anthony Liguori
                object_ref(target);
864 fe40e627 Anthony Liguori
                *child = target;
865 57c9fafe Anthony Liguori
            } else {
866 57c9fafe Anthony Liguori
                error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, type);
867 57c9fafe Anthony Liguori
            }
868 57c9fafe Anthony Liguori
869 57c9fafe Anthony Liguori
            g_free(target_type);
870 57c9fafe Anthony Liguori
        } else {
871 57c9fafe Anthony Liguori
            error_set(errp, QERR_DEVICE_NOT_FOUND, path);
872 57c9fafe Anthony Liguori
        }
873 57c9fafe Anthony Liguori
    } else {
874 57c9fafe Anthony Liguori
        *child = NULL;
875 57c9fafe Anthony Liguori
    }
876 57c9fafe Anthony Liguori
877 57c9fafe Anthony Liguori
    g_free(path);
878 57c9fafe Anthony Liguori
}
879 57c9fafe Anthony Liguori
880 57c9fafe Anthony Liguori
void object_property_add_link(Object *obj, const char *name,
881 57c9fafe Anthony Liguori
                              const char *type, Object **child,
882 57c9fafe Anthony Liguori
                              Error **errp)
883 57c9fafe Anthony Liguori
{
884 57c9fafe Anthony Liguori
    gchar *full_type;
885 57c9fafe Anthony Liguori
886 57c9fafe Anthony Liguori
    full_type = g_strdup_printf("link<%s>", type);
887 57c9fafe Anthony Liguori
888 57c9fafe Anthony Liguori
    object_property_add(obj, name, full_type,
889 57c9fafe Anthony Liguori
                        object_get_link_property,
890 57c9fafe Anthony Liguori
                        object_set_link_property,
891 57c9fafe Anthony Liguori
                        NULL, child, errp);
892 57c9fafe Anthony Liguori
893 57c9fafe Anthony Liguori
    g_free(full_type);
894 57c9fafe Anthony Liguori
}
895 57c9fafe Anthony Liguori
896 57c9fafe Anthony Liguori
gchar *object_get_canonical_path(Object *obj)
897 57c9fafe Anthony Liguori
{
898 57c9fafe Anthony Liguori
    Object *root = object_get_root();
899 57c9fafe Anthony Liguori
    char *newpath = NULL, *path = NULL;
900 57c9fafe Anthony Liguori
901 57c9fafe Anthony Liguori
    while (obj != root) {
902 57c9fafe Anthony Liguori
        ObjectProperty *prop = NULL;
903 57c9fafe Anthony Liguori
904 57c9fafe Anthony Liguori
        g_assert(obj->parent != NULL);
905 57c9fafe Anthony Liguori
906 57c9fafe Anthony Liguori
        QTAILQ_FOREACH(prop, &obj->parent->properties, node) {
907 57c9fafe Anthony Liguori
            if (!strstart(prop->type, "child<", NULL)) {
908 57c9fafe Anthony Liguori
                continue;
909 57c9fafe Anthony Liguori
            }
910 57c9fafe Anthony Liguori
911 57c9fafe Anthony Liguori
            if (prop->opaque == obj) {
912 57c9fafe Anthony Liguori
                if (path) {
913 57c9fafe Anthony Liguori
                    newpath = g_strdup_printf("%s/%s", prop->name, path);
914 57c9fafe Anthony Liguori
                    g_free(path);
915 57c9fafe Anthony Liguori
                    path = newpath;
916 57c9fafe Anthony Liguori
                } else {
917 57c9fafe Anthony Liguori
                    path = g_strdup(prop->name);
918 57c9fafe Anthony Liguori
                }
919 57c9fafe Anthony Liguori
                break;
920 57c9fafe Anthony Liguori
            }
921 57c9fafe Anthony Liguori
        }
922 57c9fafe Anthony Liguori
923 57c9fafe Anthony Liguori
        g_assert(prop != NULL);
924 57c9fafe Anthony Liguori
925 57c9fafe Anthony Liguori
        obj = obj->parent;
926 57c9fafe Anthony Liguori
    }
927 57c9fafe Anthony Liguori
928 57c9fafe Anthony Liguori
    newpath = g_strdup_printf("/%s", path);
929 57c9fafe Anthony Liguori
    g_free(path);
930 57c9fafe Anthony Liguori
931 57c9fafe Anthony Liguori
    return newpath;
932 57c9fafe Anthony Liguori
}
933 57c9fafe Anthony Liguori
934 57c9fafe Anthony Liguori
static Object *object_resolve_abs_path(Object *parent,
935 57c9fafe Anthony Liguori
                                          gchar **parts,
936 57c9fafe Anthony Liguori
                                          int index)
937 57c9fafe Anthony Liguori
{
938 57c9fafe Anthony Liguori
    ObjectProperty *prop;
939 57c9fafe Anthony Liguori
    Object *child;
940 57c9fafe Anthony Liguori
941 57c9fafe Anthony Liguori
    if (parts[index] == NULL) {
942 57c9fafe Anthony Liguori
        return parent;
943 57c9fafe Anthony Liguori
    }
944 57c9fafe Anthony Liguori
945 57c9fafe Anthony Liguori
    if (strcmp(parts[index], "") == 0) {
946 57c9fafe Anthony Liguori
        return object_resolve_abs_path(parent, parts, index + 1);
947 57c9fafe Anthony Liguori
    }
948 57c9fafe Anthony Liguori
949 57c9fafe Anthony Liguori
    prop = object_property_find(parent, parts[index]);
950 57c9fafe Anthony Liguori
    if (prop == NULL) {
951 57c9fafe Anthony Liguori
        return NULL;
952 57c9fafe Anthony Liguori
    }
953 57c9fafe Anthony Liguori
954 57c9fafe Anthony Liguori
    child = NULL;
955 57c9fafe Anthony Liguori
    if (strstart(prop->type, "link<", NULL)) {
956 57c9fafe Anthony Liguori
        Object **pchild = prop->opaque;
957 57c9fafe Anthony Liguori
        if (*pchild) {
958 57c9fafe Anthony Liguori
            child = *pchild;
959 57c9fafe Anthony Liguori
        }
960 57c9fafe Anthony Liguori
    } else if (strstart(prop->type, "child<", NULL)) {
961 57c9fafe Anthony Liguori
        child = prop->opaque;
962 57c9fafe Anthony Liguori
    }
963 57c9fafe Anthony Liguori
964 57c9fafe Anthony Liguori
    if (!child) {
965 57c9fafe Anthony Liguori
        return NULL;
966 57c9fafe Anthony Liguori
    }
967 57c9fafe Anthony Liguori
968 57c9fafe Anthony Liguori
    return object_resolve_abs_path(child, parts, index + 1);
969 57c9fafe Anthony Liguori
}
970 57c9fafe Anthony Liguori
971 57c9fafe Anthony Liguori
static Object *object_resolve_partial_path(Object *parent,
972 57c9fafe Anthony Liguori
                                              gchar **parts,
973 57c9fafe Anthony Liguori
                                              bool *ambiguous)
974 57c9fafe Anthony Liguori
{
975 57c9fafe Anthony Liguori
    Object *obj;
976 57c9fafe Anthony Liguori
    ObjectProperty *prop;
977 57c9fafe Anthony Liguori
978 57c9fafe Anthony Liguori
    obj = object_resolve_abs_path(parent, parts, 0);
979 57c9fafe Anthony Liguori
980 57c9fafe Anthony Liguori
    QTAILQ_FOREACH(prop, &parent->properties, node) {
981 57c9fafe Anthony Liguori
        Object *found;
982 57c9fafe Anthony Liguori
983 57c9fafe Anthony Liguori
        if (!strstart(prop->type, "child<", NULL)) {
984 57c9fafe Anthony Liguori
            continue;
985 57c9fafe Anthony Liguori
        }
986 57c9fafe Anthony Liguori
987 57c9fafe Anthony Liguori
        found = object_resolve_partial_path(prop->opaque, parts, ambiguous);
988 57c9fafe Anthony Liguori
        if (found) {
989 57c9fafe Anthony Liguori
            if (obj) {
990 57c9fafe Anthony Liguori
                if (ambiguous) {
991 57c9fafe Anthony Liguori
                    *ambiguous = true;
992 57c9fafe Anthony Liguori
                }
993 57c9fafe Anthony Liguori
                return NULL;
994 57c9fafe Anthony Liguori
            }
995 57c9fafe Anthony Liguori
            obj = found;
996 57c9fafe Anthony Liguori
        }
997 57c9fafe Anthony Liguori
998 57c9fafe Anthony Liguori
        if (ambiguous && *ambiguous) {
999 57c9fafe Anthony Liguori
            return NULL;
1000 57c9fafe Anthony Liguori
        }
1001 57c9fafe Anthony Liguori
    }
1002 57c9fafe Anthony Liguori
1003 57c9fafe Anthony Liguori
    return obj;
1004 57c9fafe Anthony Liguori
}
1005 57c9fafe Anthony Liguori
1006 57c9fafe Anthony Liguori
Object *object_resolve_path(const char *path, bool *ambiguous)
1007 57c9fafe Anthony Liguori
{
1008 57c9fafe Anthony Liguori
    bool partial_path = true;
1009 57c9fafe Anthony Liguori
    Object *obj;
1010 57c9fafe Anthony Liguori
    gchar **parts;
1011 57c9fafe Anthony Liguori
1012 57c9fafe Anthony Liguori
    parts = g_strsplit(path, "/", 0);
1013 57c9fafe Anthony Liguori
    if (parts == NULL || parts[0] == NULL) {
1014 57c9fafe Anthony Liguori
        g_strfreev(parts);
1015 57c9fafe Anthony Liguori
        return object_get_root();
1016 57c9fafe Anthony Liguori
    }
1017 57c9fafe Anthony Liguori
1018 57c9fafe Anthony Liguori
    if (strcmp(parts[0], "") == 0) {
1019 57c9fafe Anthony Liguori
        partial_path = false;
1020 57c9fafe Anthony Liguori
    }
1021 57c9fafe Anthony Liguori
1022 57c9fafe Anthony Liguori
    if (partial_path) {
1023 57c9fafe Anthony Liguori
        if (ambiguous) {
1024 57c9fafe Anthony Liguori
            *ambiguous = false;
1025 57c9fafe Anthony Liguori
        }
1026 57c9fafe Anthony Liguori
        obj = object_resolve_partial_path(object_get_root(), parts, ambiguous);
1027 57c9fafe Anthony Liguori
    } else {
1028 57c9fafe Anthony Liguori
        obj = object_resolve_abs_path(object_get_root(), parts, 1);
1029 57c9fafe Anthony Liguori
    }
1030 57c9fafe Anthony Liguori
1031 57c9fafe Anthony Liguori
    g_strfreev(parts);
1032 57c9fafe Anthony Liguori
1033 57c9fafe Anthony Liguori
    return obj;
1034 57c9fafe Anthony Liguori
}
1035 57c9fafe Anthony Liguori
1036 57c9fafe Anthony Liguori
typedef struct StringProperty
1037 57c9fafe Anthony Liguori
{
1038 57c9fafe Anthony Liguori
    char *(*get)(Object *, Error **);
1039 57c9fafe Anthony Liguori
    void (*set)(Object *, const char *, Error **);
1040 57c9fafe Anthony Liguori
} StringProperty;
1041 57c9fafe Anthony Liguori
1042 7b7b7d18 Paolo Bonzini
static void property_get_str(Object *obj, Visitor *v, void *opaque,
1043 7b7b7d18 Paolo Bonzini
                             const char *name, Error **errp)
1044 57c9fafe Anthony Liguori
{
1045 57c9fafe Anthony Liguori
    StringProperty *prop = opaque;
1046 57c9fafe Anthony Liguori
    char *value;
1047 57c9fafe Anthony Liguori
1048 57c9fafe Anthony Liguori
    value = prop->get(obj, errp);
1049 57c9fafe Anthony Liguori
    if (value) {
1050 57c9fafe Anthony Liguori
        visit_type_str(v, &value, name, errp);
1051 57c9fafe Anthony Liguori
        g_free(value);
1052 57c9fafe Anthony Liguori
    }
1053 57c9fafe Anthony Liguori
}
1054 57c9fafe Anthony Liguori
1055 7b7b7d18 Paolo Bonzini
static void property_set_str(Object *obj, Visitor *v, void *opaque,
1056 7b7b7d18 Paolo Bonzini
                             const char *name, Error **errp)
1057 57c9fafe Anthony Liguori
{
1058 57c9fafe Anthony Liguori
    StringProperty *prop = opaque;
1059 57c9fafe Anthony Liguori
    char *value;
1060 57c9fafe Anthony Liguori
    Error *local_err = NULL;
1061 57c9fafe Anthony Liguori
1062 57c9fafe Anthony Liguori
    visit_type_str(v, &value, name, &local_err);
1063 57c9fafe Anthony Liguori
    if (local_err) {
1064 57c9fafe Anthony Liguori
        error_propagate(errp, local_err);
1065 57c9fafe Anthony Liguori
        return;
1066 57c9fafe Anthony Liguori
    }
1067 57c9fafe Anthony Liguori
1068 57c9fafe Anthony Liguori
    prop->set(obj, value, errp);
1069 57c9fafe Anthony Liguori
    g_free(value);
1070 57c9fafe Anthony Liguori
}
1071 57c9fafe Anthony Liguori
1072 7b7b7d18 Paolo Bonzini
static void property_release_str(Object *obj, const char *name,
1073 7b7b7d18 Paolo Bonzini
                                 void *opaque)
1074 57c9fafe Anthony Liguori
{
1075 57c9fafe Anthony Liguori
    StringProperty *prop = opaque;
1076 57c9fafe Anthony Liguori
    g_free(prop);
1077 57c9fafe Anthony Liguori
}
1078 57c9fafe Anthony Liguori
1079 57c9fafe Anthony Liguori
void object_property_add_str(Object *obj, const char *name,
1080 57c9fafe Anthony Liguori
                           char *(*get)(Object *, Error **),
1081 57c9fafe Anthony Liguori
                           void (*set)(Object *, const char *, Error **),
1082 57c9fafe Anthony Liguori
                           Error **errp)
1083 57c9fafe Anthony Liguori
{
1084 57c9fafe Anthony Liguori
    StringProperty *prop = g_malloc0(sizeof(*prop));
1085 57c9fafe Anthony Liguori
1086 57c9fafe Anthony Liguori
    prop->get = get;
1087 57c9fafe Anthony Liguori
    prop->set = set;
1088 57c9fafe Anthony Liguori
1089 57c9fafe Anthony Liguori
    object_property_add(obj, name, "string",
1090 7b7b7d18 Paolo Bonzini
                        get ? property_get_str : NULL,
1091 7b7b7d18 Paolo Bonzini
                        set ? property_set_str : NULL,
1092 7b7b7d18 Paolo Bonzini
                        property_release_str,
1093 57c9fafe Anthony Liguori
                        prop, errp);
1094 57c9fafe Anthony Liguori
}