Statistics
| Branch: | Revision:

root / qom / object.c @ 371c6489

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