Statistics
| Branch: | Revision:

root / qom / object.c @ aca59af6

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