Statistics
| Branch: | Revision:

root / qom / object.c @ 049cb3cf

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