Statistics
| Branch: | Revision:

root / qom / object.c @ 17862378

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