#include "qemu/object.h"
#include "qemu-common.h"
#include "qapi/qapi-visit-core.h"
+#include "qapi/string-input-visitor.h"
+#include "qapi/string-output-visitor.h"
/* TODO: replace QObject with a simpler visitor to avoid a dependency
* of the QOM core on QObject? */
return sizeof(ObjectClass);
}
+static size_t type_object_get_size(TypeImpl *ti)
+{
+ if (ti->instance_size) {
+ return ti->instance_size;
+ }
+
+ if (type_has_parent(ti)) {
+ return type_object_get_size(type_get_parent(ti));
+ }
+
+ return 0;
+}
+
static void type_class_interface_init(TypeImpl *ti, InterfaceImpl *iface)
{
TypeInfo info = {
g_free(name);
}
-static void type_class_init(TypeImpl *ti)
+static void type_initialize(TypeImpl *ti)
{
size_t class_size = sizeof(ObjectClass);
int i;
}
ti->class_size = type_class_get_size(ti);
+ ti->instance_size = type_object_get_size(ti);
ti->class = g_malloc0(ti->class_size);
ti->class->type = ti;
if (type_has_parent(ti)) {
TypeImpl *parent = type_get_parent(ti);
- type_class_init(parent);
+ type_initialize(parent);
class_size = parent->class_size;
g_assert(parent->class_size <= ti->class_size);
Object *obj = data;
g_assert(type != NULL);
- g_assert(type->instance_size >= sizeof(ObjectClass));
+ type_initialize(type);
- type_class_init(type);
+ g_assert(type->instance_size >= sizeof(Object));
g_assert(type->abstract == false);
memset(obj, 0, type->instance_size);
ObjectProperty *prop;
QTAILQ_FOREACH(prop, &obj->properties, node) {
- if (!strstart(prop->type, "child<", NULL)) {
- continue;
- }
-
- if (prop->opaque == child) {
+ if (strstart(prop->type, "child<", NULL) && prop->opaque == child) {
object_property_del(obj, prop->name, errp);
+ break;
}
}
}
Object *obj;
g_assert(type != NULL);
+ type_initialize(type);
obj = g_malloc(type->instance_size);
object_initialize_with_type(obj, type);
}
-static void register_interface(void)
+static void register_types(void)
{
static TypeInfo interface_info = {
.name = TYPE_INTERFACE,
type_interface = type_register_static(&interface_info);
}
-device_init(register_interface);
+type_init(register_types)
Object *object_dynamic_cast_assert(Object *obj, const char *typename)
{
return NULL;
}
- type_class_init(type);
+ type_initialize(type);
return type->class;
}
TypeImpl *type = value;
ObjectClass *k;
- type_class_init(type);
+ type_initialize(type);
k = type->class;
if (!data->include_abstract && type->abstract) {
g_hash_table_foreach(type_table_get(), object_class_foreach_tramp, &data);
}
+static void object_class_get_list_tramp(ObjectClass *klass, void *opaque)
+{
+ GSList **list = opaque;
+
+ *list = g_slist_prepend(*list, klass);
+}
+
+GSList *object_class_get_list(const char *implements_type,
+ bool include_abstract)
+{
+ GSList *list = NULL;
+
+ object_class_foreach(object_class_get_list_tramp,
+ implements_type, include_abstract, &list);
+ return list;
+}
+
void object_ref(Object *obj)
{
obj->ref++;
return retval;
}
+void object_property_set_link(Object *obj, Object *value,
+ const char *name, Error **errp)
+{
+ object_property_set_str(obj, object_get_canonical_path(value),
+ name, errp);
+}
+
+Object *object_property_get_link(Object *obj, const char *name,
+ Error **errp)
+{
+ char *str = object_property_get_str(obj, name, errp);
+ Object *target = NULL;
+
+ if (str && *str) {
+ target = object_resolve_path(str, NULL);
+ if (!target) {
+ error_set(errp, QERR_DEVICE_NOT_FOUND, str);
+ }
+ }
+
+ g_free(str);
+ return target;
+}
+
void object_property_set_bool(Object *obj, bool value,
const char *name, Error **errp)
{
return retval;
}
+void object_property_parse(Object *obj, const char *string,
+ const char *name, Error **errp)
+{
+ StringInputVisitor *mi;
+ mi = string_input_visitor_new(string);
+ object_property_set(obj, string_input_get_visitor(mi), name, errp);
+
+ string_input_visitor_cleanup(mi);
+}
+
+char *object_property_print(Object *obj, const char *name,
+ Error **errp)
+{
+ StringOutputVisitor *mo;
+ char *string;
+
+ mo = string_output_visitor_new();
+ object_property_get(obj, string_output_get_visitor(mo), name, NULL);
+ string = string_output_get_string(mo);
+ string_output_visitor_cleanup(mo);
+ return string;
+}
+
const char *object_property_get_type(Object *obj, const char *name, Error **errp)
{
ObjectProperty *prop = object_property_find(obj, name);
{
gchar *type;
+ /* Registering an interface object in the composition tree will mightily
+ * confuse object_get_canonical_path (which, on the other hand, knows how
+ * to get the canonical path of an interface object).
+ */
+ assert(!object_is_type(obj, type_interface));
+
type = g_strdup_printf("child<%s>", object_get_typename(OBJECT(child)));
object_property_add(obj, name, type, object_get_child_property,
const char *name, Error **errp)
{
Object **child = opaque;
+ Object *old_target;
bool ambiguous = false;
const char *type;
char *path;
+ gchar *target_type;
type = object_property_get_type(obj, name, NULL);
visit_type_str(v, &path, name, errp);
- if (*child) {
- object_unref(*child);
- }
+ old_target = *child;
+ *child = NULL;
if (strcmp(path, "") != 0) {
Object *target;
- target = object_resolve_path(path, &ambiguous);
- if (target) {
- /* Go from link<FOO> to FOO. */
- gchar *target_type = g_strndup(&type[5], strlen(type) - 6);
- if (object_dynamic_cast(target, target_type)) {
- object_ref(target);
- *child = target;
- } else {
- error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, type);
- }
+ /* Go from link<FOO> to FOO. */
+ target_type = g_strndup(&type[5], strlen(type) - 6);
+ target = object_resolve_path_type(path, target_type, &ambiguous);
- g_free(target_type);
+ if (ambiguous) {
+ error_set(errp, QERR_AMBIGUOUS_PATH, path);
+ } else if (target) {
+ object_ref(target);
+ *child = target;
} else {
- error_set(errp, QERR_DEVICE_NOT_FOUND, path);
+ target = object_resolve_path(path, &ambiguous);
+ if (target || ambiguous) {
+ error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, target_type);
+ } else {
+ error_set(errp, QERR_DEVICE_NOT_FOUND, path);
+ }
}
- } else {
- *child = NULL;
+ g_free(target_type);
}
g_free(path);
+
+ if (old_target != NULL) {
+ object_unref(old_target);
+ }
}
void object_property_add_link(Object *obj, const char *name,
Object *root = object_get_root();
char *newpath = NULL, *path = NULL;
+ if (object_is_type(obj, type_interface)) {
+ obj = INTERFACE(obj)->obj;
+ }
+
while (obj != root) {
ObjectProperty *prop = NULL;
return newpath;
}
+Object *object_resolve_path_component(Object *parent, gchar *part)
+{
+ ObjectProperty *prop = object_property_find(parent, part);
+ if (prop == NULL) {
+ return NULL;
+ }
+
+ if (strstart(prop->type, "link<", NULL)) {
+ return *(Object **)prop->opaque;
+ } else if (strstart(prop->type, "child<", NULL)) {
+ return prop->opaque;
+ } else {
+ return NULL;
+ }
+}
+
static Object *object_resolve_abs_path(Object *parent,
gchar **parts,
const char *typename,
int index)
{
- ObjectProperty *prop;
Object *child;
if (parts[index] == NULL) {
return object_resolve_abs_path(parent, parts, typename, index + 1);
}
- prop = object_property_find(parent, parts[index]);
- if (prop == NULL) {
- return NULL;
- }
-
- child = NULL;
- if (strstart(prop->type, "link<", NULL)) {
- Object **pchild = prop->opaque;
- if (*pchild) {
- child = *pchild;
- }
- } else if (strstart(prop->type, "child<", NULL)) {
- child = prop->opaque;
- }
-
+ child = object_resolve_path_component(parent, parts[index]);
if (!child) {
return NULL;
}