diff options
Diffstat (limited to 'qemu/qom/object.c')
-rw-r--r-- | qemu/qom/object.c | 570 |
1 files changed, 437 insertions, 133 deletions
diff --git a/qemu/qom/object.c b/qemu/qom/object.c index eea8edf3d..8e6e68dff 100644 --- a/qemu/qom/object.c +++ b/qemu/qom/object.c @@ -10,9 +10,11 @@ * See the COPYING file in the top-level directory. */ +#include "qemu/osdep.h" +#include "qapi/error.h" #include "qom/object.h" #include "qom/object_interfaces.h" -#include "qemu-common.h" +#include "qemu/cutils.h" #include "qapi/visitor.h" #include "qapi-visit.h" #include "qapi/string-input-visitor.h" @@ -204,7 +206,7 @@ static bool type_is_ancestor(TypeImpl *type, TypeImpl *target_type) { assert(target_type); - /* Check if typename is a direct ancestor of type */ + /* Check if target_type is a direct ancestor of type */ while (type) { if (type == target_type) { return true; @@ -242,6 +244,16 @@ static void type_initialize_interface(TypeImpl *ti, TypeImpl *interface_type, iface_impl->class); } +static void object_property_free(gpointer data) +{ + ObjectProperty *prop = data; + + g_free(prop->name); + g_free(prop->type); + g_free(prop->description); + g_free(prop); +} + static void type_initialize(TypeImpl *ti) { TypeImpl *parent; @@ -261,9 +273,11 @@ static void type_initialize(TypeImpl *ti) GSList *e; int i; - g_assert(parent->class_size <= ti->class_size); + g_assert_cmpint(parent->class_size, <=, ti->class_size); memcpy(ti->class, parent->class, parent->class_size); ti->class->interfaces = NULL; + ti->class->properties = g_hash_table_new_full( + g_str_hash, g_str_equal, g_free, object_property_free); for (e = parent->class->interfaces; e; e = e->next) { InterfaceClass *iface = e->data; @@ -288,6 +302,9 @@ static void type_initialize(TypeImpl *ti) type_initialize_interface(ti, t, t); } + } else { + ti->class->properties = g_hash_table_new_full( + g_str_hash, g_str_equal, g_free, object_property_free); } ti->class->type = ti; @@ -333,14 +350,15 @@ void object_initialize_with_type(void *data, size_t size, TypeImpl *type) g_assert(type != NULL); type_initialize(type); - g_assert(type->instance_size >= sizeof(Object)); + g_assert_cmpint(type->instance_size, >=, sizeof(Object)); g_assert(type->abstract == false); - g_assert(size >= type->instance_size); + g_assert_cmpint(size, >=, type->instance_size); memset(obj, 0, type->instance_size); obj->class = type->class; object_ref(obj); - QTAILQ_INIT(&obj->properties); + obj->properties = g_hash_table_new_full(g_str_hash, g_str_equal, + NULL, object_property_free); object_init_with_type(obj, type); object_post_init_with_type(obj, type); } @@ -359,29 +377,51 @@ static inline bool object_property_is_child(ObjectProperty *prop) static void object_property_del_all(Object *obj) { - while (!QTAILQ_EMPTY(&obj->properties)) { - ObjectProperty *prop = QTAILQ_FIRST(&obj->properties); - - QTAILQ_REMOVE(&obj->properties, prop, node); - - if (prop->release) { - prop->release(obj, prop->name, prop->opaque); + ObjectProperty *prop; + GHashTableIter iter; + gpointer key, value; + bool released; + + do { + released = false; + g_hash_table_iter_init(&iter, obj->properties); + while (g_hash_table_iter_next(&iter, &key, &value)) { + prop = value; + if (prop->release) { + prop->release(obj, prop->name, prop->opaque); + prop->release = NULL; + released = true; + break; + } + g_hash_table_iter_remove(&iter); } + } while (released); - g_free(prop->name); - g_free(prop->type); - g_free(prop->description); - g_free(prop); - } + g_hash_table_unref(obj->properties); } static void object_property_del_child(Object *obj, Object *child, Error **errp) { ObjectProperty *prop; + GHashTableIter iter; + gpointer key, value; - QTAILQ_FOREACH(prop, &obj->properties, node) { + g_hash_table_iter_init(&iter, obj->properties); + while (g_hash_table_iter_next(&iter, &key, &value)) { + prop = value; + if (object_property_is_child(prop) && prop->opaque == child) { + if (prop->release) { + prop->release(obj, prop->name, prop->opaque); + prop->release = NULL; + } + break; + } + } + g_hash_table_iter_init(&iter, obj->properties); + while (g_hash_table_iter_next(&iter, &key, &value)) { + prop = value; if (object_property_is_child(prop) && prop->opaque == child) { - object_property_del(obj, prop->name, errp); + g_hash_table_iter_remove(&iter); break; } } @@ -413,7 +453,7 @@ static void object_finalize(void *data) object_property_del_all(obj); object_deinit(obj, ti); - g_assert(obj->ref == 0); + g_assert_cmpint(obj->ref, ==, 0); if (obj->free) { obj->free(obj); } @@ -775,23 +815,44 @@ void object_class_foreach(void (*fn)(ObjectClass *klass, void *opaque), enumerating_types = false; } -int object_child_foreach(Object *obj, int (*fn)(Object *child, void *opaque), - void *opaque) +static int do_object_child_foreach(Object *obj, + int (*fn)(Object *child, void *opaque), + void *opaque, bool recurse) { - ObjectProperty *prop, *next; + GHashTableIter iter; + ObjectProperty *prop; int ret = 0; - QTAILQ_FOREACH_SAFE(prop, &obj->properties, node, next) { + g_hash_table_iter_init(&iter, obj->properties); + while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&prop)) { if (object_property_is_child(prop)) { - ret = fn(prop->opaque, opaque); + Object *child = prop->opaque; + + ret = fn(child, opaque); if (ret != 0) { break; } + if (recurse) { + do_object_child_foreach(child, fn, opaque, true); + } } } return ret; } +int object_child_foreach(Object *obj, int (*fn)(Object *child, void *opaque), + void *opaque) +{ + return do_object_child_foreach(obj, fn, opaque, false); +} + +int object_child_foreach_recursive(Object *obj, + int (*fn)(Object *child, void *opaque), + void *opaque) +{ + return do_object_child_foreach(obj, fn, opaque, true); +} + static void object_class_get_list_tramp(ObjectClass *klass, void *opaque) { GSList **list = opaque; @@ -814,7 +875,7 @@ void object_ref(Object *obj) if (!obj) { return; } - atomic_inc(&obj->ref); + atomic_inc(&obj->ref); } void object_unref(Object *obj) @@ -822,7 +883,7 @@ void object_unref(Object *obj) if (!obj) { return; } - g_assert(obj->ref > 0); + g_assert_cmpint(obj->ref, >, 0); /* parent always holds a reference to its children */ if (atomic_fetch_dec(&obj->ref) == 1) { @@ -860,13 +921,11 @@ object_property_add(Object *obj, const char *name, const char *type, return ret; } - QTAILQ_FOREACH(prop, &obj->properties, node) { - if (strcmp(prop->name, name) == 0) { - error_setg(errp, "attempt to add duplicate property '%s'" - " to object (type '%s')", name, - object_get_typename(obj)); - return NULL; - } + if (object_property_find(obj, name, NULL) != NULL) { + error_setg(errp, "attempt to add duplicate property '%s'" + " to object (type '%s')", name, + object_get_typename(obj)); + return NULL; } prop = g_malloc0(sizeof(*prop)); @@ -879,7 +938,41 @@ object_property_add(Object *obj, const char *name, const char *type, prop->release = release; prop->opaque = opaque; - QTAILQ_INSERT_TAIL(&obj->properties, prop, node); + g_hash_table_insert(obj->properties, prop->name, prop); + return prop; +} + +ObjectProperty * +object_class_property_add(ObjectClass *klass, + const char *name, + const char *type, + ObjectPropertyAccessor *get, + ObjectPropertyAccessor *set, + ObjectPropertyRelease *release, + void *opaque, + Error **errp) +{ + ObjectProperty *prop; + + if (object_class_property_find(klass, name, NULL) != NULL) { + error_setg(errp, "attempt to add duplicate property '%s'" + " to object (type '%s')", name, + object_class_get_name(klass)); + return NULL; + } + + prop = g_malloc0(sizeof(*prop)); + + prop->name = g_strdup(name); + prop->type = g_strdup(type); + + prop->get = get; + prop->set = set; + prop->release = release; + prop->opaque = opaque; + + g_hash_table_insert(klass->properties, g_strdup(name), prop); + return prop; } @@ -887,34 +980,76 @@ ObjectProperty *object_property_find(Object *obj, const char *name, Error **errp) { ObjectProperty *prop; + ObjectClass *klass = object_get_class(obj); - QTAILQ_FOREACH(prop, &obj->properties, node) { - if (strcmp(prop->name, name) == 0) { - return prop; - } + prop = object_class_property_find(klass, name, NULL); + if (prop) { + return prop; + } + + prop = g_hash_table_lookup(obj->properties, name); + if (prop) { + return prop; } error_setg(errp, "Property '.%s' not found", name); return NULL; } +void object_property_iter_init(ObjectPropertyIterator *iter, + Object *obj) +{ + g_hash_table_iter_init(&iter->iter, obj->properties); + iter->nextclass = object_get_class(obj); +} + +ObjectProperty *object_property_iter_next(ObjectPropertyIterator *iter) +{ + gpointer key, val; + while (!g_hash_table_iter_next(&iter->iter, &key, &val)) { + if (!iter->nextclass) { + return NULL; + } + g_hash_table_iter_init(&iter->iter, iter->nextclass->properties); + iter->nextclass = object_class_get_parent(iter->nextclass); + } + return val; +} + +ObjectProperty *object_class_property_find(ObjectClass *klass, const char *name, + Error **errp) +{ + ObjectProperty *prop; + ObjectClass *parent_klass; + + parent_klass = object_class_get_parent(klass); + if (parent_klass) { + prop = object_class_property_find(parent_klass, name, NULL); + if (prop) { + return prop; + } + } + + prop = g_hash_table_lookup(klass->properties, name); + if (!prop) { + error_setg(errp, "Property '.%s' not found", name); + } + return prop; +} + void object_property_del(Object *obj, const char *name, Error **errp) { - ObjectProperty *prop = object_property_find(obj, name, errp); - if (prop == NULL) { + ObjectProperty *prop = g_hash_table_lookup(obj->properties, name); + + if (!prop) { + error_setg(errp, "Property '.%s' not found", name); return; } if (prop->release) { prop->release(obj, name, prop->opaque); } - - QTAILQ_REMOVE(&obj->properties, prop, node); - - g_free(prop->name); - g_free(prop->type); - g_free(prop->description); - g_free(prop); + g_hash_table_remove(obj->properties, name); } void object_property_get(Object *obj, Visitor *v, const char *name, @@ -928,7 +1063,7 @@ void object_property_get(Object *obj, Visitor *v, const char *name, if (!prop->get) { error_setg(errp, QERR_PERMISSION_DENIED); } else { - prop->get(obj, v, prop->opaque, name, errp); + prop->get(obj, v, name, prop->opaque, errp); } } @@ -943,7 +1078,7 @@ void object_property_set(Object *obj, Visitor *v, const char *name, if (!prop->set) { error_setg(errp, QERR_PERMISSION_DENIED); } else { - prop->set(obj, v, prop->opaque, name, errp); + prop->set(obj, v, name, prop->opaque, errp); } } @@ -1079,6 +1214,7 @@ typedef struct EnumProperty { int object_property_get_enum(Object *obj, const char *name, const char *typename, Error **errp) { + Error *err = NULL; StringOutputVisitor *sov; StringInputVisitor *siv; char *str; @@ -1100,12 +1236,17 @@ int object_property_get_enum(Object *obj, const char *name, enumprop = prop->opaque; sov = string_output_visitor_new(false); - object_property_get(obj, string_output_get_visitor(sov), name, errp); + object_property_get(obj, string_output_get_visitor(sov), name, &err); + if (err) { + error_propagate(errp, err); + string_output_visitor_cleanup(sov); + return 0; + } str = string_output_get_string(sov); siv = string_input_visitor_new(str); string_output_visitor_cleanup(sov); - visit_type_enum(string_input_get_visitor(siv), - &ret, enumprop->strings, NULL, name, errp); + visit_type_enum(string_input_get_visitor(siv), name, &ret, + enumprop->strings, errp); g_free(str); string_input_visitor_cleanup(siv); @@ -1116,51 +1257,56 @@ int object_property_get_enum(Object *obj, const char *name, void object_property_get_uint16List(Object *obj, const char *name, uint16List **list, Error **errp) { + Error *err = NULL; StringOutputVisitor *ov; StringInputVisitor *iv; char *str; ov = string_output_visitor_new(false); object_property_get(obj, string_output_get_visitor(ov), - name, errp); + name, &err); + if (err) { + error_propagate(errp, err); + goto out; + } str = string_output_get_string(ov); iv = string_input_visitor_new(str); - visit_type_uint16List(string_input_get_visitor(iv), - list, NULL, errp); + visit_type_uint16List(string_input_get_visitor(iv), NULL, list, errp); g_free(str); - string_output_visitor_cleanup(ov); string_input_visitor_cleanup(iv); +out: + string_output_visitor_cleanup(ov); } 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); + StringInputVisitor *siv; + siv = string_input_visitor_new(string); + object_property_set(obj, string_input_get_visitor(siv), name, errp); - string_input_visitor_cleanup(mi); + string_input_visitor_cleanup(siv); } char *object_property_print(Object *obj, const char *name, bool human, Error **errp) { - StringOutputVisitor *mo; + StringOutputVisitor *sov; char *string = NULL; Error *local_err = NULL; - mo = string_output_visitor_new(human); - object_property_get(obj, string_output_get_visitor(mo), name, &local_err); + sov = string_output_visitor_new(human); + object_property_get(obj, string_output_get_visitor(sov), name, &local_err); if (local_err) { error_propagate(errp, local_err); goto out; } - string = string_output_get_string(mo); + string = string_output_get_string(sov); out: - string_output_visitor_cleanup(mo); + string_output_visitor_cleanup(sov); return string; } @@ -1190,14 +1336,15 @@ Object *object_get_objects_root(void) return container_get(object_get_root(), "/objects"); } -static void object_get_child_property(Object *obj, Visitor *v, void *opaque, - const char *name, Error **errp) +static void object_get_child_property(Object *obj, Visitor *v, + const char *name, void *opaque, + Error **errp) { Object *child = opaque; gchar *path; path = object_get_canonical_path(child); - visit_type_str(v, &path, name, errp); + visit_type_str(v, name, &path, errp); g_free(path); } @@ -1259,8 +1406,9 @@ typedef struct { ObjectPropertyLinkFlags flags; } LinkProperty; -static void object_get_link_property(Object *obj, Visitor *v, void *opaque, - const char *name, Error **errp) +static void object_get_link_property(Object *obj, Visitor *v, + const char *name, void *opaque, + Error **errp) { LinkProperty *lprop = opaque; Object **child = lprop->child; @@ -1268,11 +1416,11 @@ static void object_get_link_property(Object *obj, Visitor *v, void *opaque, if (*child) { path = object_get_canonical_path(*child); - visit_type_str(v, &path, name, errp); + visit_type_str(v, name, &path, errp); g_free(path); } else { path = (gchar *)""; - visit_type_str(v, &path, name, errp); + visit_type_str(v, name, &path, errp); } } @@ -1299,8 +1447,8 @@ static Object *object_resolve_link(Object *obj, const char *name, target = object_resolve_path_type(path, target_type, &ambiguous); if (ambiguous) { - error_set(errp, ERROR_CLASS_GENERIC_ERROR, - "Path '%s' does not uniquely identify an object", path); + error_setg(errp, "Path '%s' does not uniquely identify an object", + path); } else if (!target) { target = object_resolve_path(path, &ambiguous); if (target || ambiguous) { @@ -1316,8 +1464,9 @@ static Object *object_resolve_link(Object *obj, const char *name, return target; } -static void object_set_link_property(Object *obj, Visitor *v, void *opaque, - const char *name, Error **errp) +static void object_set_link_property(Object *obj, Visitor *v, + const char *name, void *opaque, + Error **errp) { Error *local_err = NULL; LinkProperty *prop = opaque; @@ -1326,7 +1475,7 @@ static void object_set_link_property(Object *obj, Visitor *v, void *opaque, Object *new_target = NULL; char *path = NULL; - visit_type_str(v, &path, name, &local_err); + visit_type_str(v, name, &path, &local_err); if (!local_err && strcmp(path, "") != 0) { new_target = object_resolve_link(obj, name, path, &local_err); @@ -1422,11 +1571,13 @@ void object_property_add_const_link(Object *obj, const char *name, gchar *object_get_canonical_path_component(Object *obj) { ObjectProperty *prop = NULL; + GHashTableIter iter; g_assert(obj); g_assert(obj->parent != NULL); - QTAILQ_FOREACH(prop, &obj->parent->properties, node) { + g_hash_table_iter_init(&iter, obj->parent->properties); + while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&prop)) { if (!object_property_is_child(prop)) { continue; } @@ -1510,11 +1661,13 @@ static Object *object_resolve_partial_path(Object *parent, bool *ambiguous) { Object *obj; + GHashTableIter iter; ObjectProperty *prop; obj = object_resolve_abs_path(parent, parts, typename, 0); - QTAILQ_FOREACH(prop, &parent->properties, node) { + g_hash_table_iter_init(&iter, parent->properties); + while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&prop)) { Object *found; if (!object_property_is_child(prop)) { @@ -1576,27 +1729,31 @@ typedef struct StringProperty void (*set)(Object *, const char *, Error **); } StringProperty; -static void property_get_str(Object *obj, Visitor *v, void *opaque, - const char *name, Error **errp) +static void property_get_str(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) { StringProperty *prop = opaque; char *value; + Error *err = NULL; - value = prop->get(obj, errp); - if (value) { - visit_type_str(v, &value, name, errp); - g_free(value); + value = prop->get(obj, &err); + if (err) { + error_propagate(errp, err); + return; } + + visit_type_str(v, name, &value, errp); + g_free(value); } -static void property_set_str(Object *obj, Visitor *v, void *opaque, - const char *name, Error **errp) +static void property_set_str(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) { StringProperty *prop = opaque; char *value; Error *local_err = NULL; - visit_type_str(v, &value, name, &local_err); + visit_type_str(v, name, &value, &local_err); if (local_err) { error_propagate(errp, local_err); return; @@ -1635,30 +1792,59 @@ void object_property_add_str(Object *obj, const char *name, } } +void object_class_property_add_str(ObjectClass *klass, const char *name, + char *(*get)(Object *, Error **), + void (*set)(Object *, const char *, + Error **), + Error **errp) +{ + Error *local_err = NULL; + StringProperty *prop = g_malloc0(sizeof(*prop)); + + prop->get = get; + prop->set = set; + + object_class_property_add(klass, name, "string", + get ? property_get_str : NULL, + set ? property_set_str : NULL, + property_release_str, + prop, &local_err); + if (local_err) { + error_propagate(errp, local_err); + g_free(prop); + } +} + typedef struct BoolProperty { bool (*get)(Object *, Error **); void (*set)(Object *, bool, Error **); } BoolProperty; -static void property_get_bool(Object *obj, Visitor *v, void *opaque, - const char *name, Error **errp) +static void property_get_bool(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) { BoolProperty *prop = opaque; bool value; + Error *err = NULL; + + value = prop->get(obj, &err); + if (err) { + error_propagate(errp, err); + return; + } - value = prop->get(obj, errp); - visit_type_bool(v, &value, name, errp); + visit_type_bool(v, name, &value, errp); } -static void property_set_bool(Object *obj, Visitor *v, void *opaque, - const char *name, Error **errp) +static void property_set_bool(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) { BoolProperty *prop = opaque; bool value; Error *local_err = NULL; - visit_type_bool(v, &value, name, &local_err); + visit_type_bool(v, name, &value, &local_err); if (local_err) { error_propagate(errp, local_err); return; @@ -1696,23 +1882,56 @@ void object_property_add_bool(Object *obj, const char *name, } } -static void property_get_enum(Object *obj, Visitor *v, void *opaque, - const char *name, Error **errp) +void object_class_property_add_bool(ObjectClass *klass, const char *name, + bool (*get)(Object *, Error **), + void (*set)(Object *, bool, Error **), + Error **errp) +{ + Error *local_err = NULL; + BoolProperty *prop = g_malloc0(sizeof(*prop)); + + prop->get = get; + prop->set = set; + + object_class_property_add(klass, name, "bool", + get ? property_get_bool : NULL, + set ? property_set_bool : NULL, + property_release_bool, + prop, &local_err); + if (local_err) { + error_propagate(errp, local_err); + g_free(prop); + } +} + +static void property_get_enum(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) { EnumProperty *prop = opaque; int value; + Error *err = NULL; - value = prop->get(obj, errp); - visit_type_enum(v, &value, prop->strings, NULL, name, errp); + value = prop->get(obj, &err); + if (err) { + error_propagate(errp, err); + return; + } + + visit_type_enum(v, name, &value, prop->strings, errp); } -static void property_set_enum(Object *obj, Visitor *v, void *opaque, - const char *name, Error **errp) +static void property_set_enum(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) { EnumProperty *prop = opaque; int value; + Error *err = NULL; - visit_type_enum(v, &value, prop->strings, NULL, name, errp); + visit_type_enum(v, name, &value, prop->strings, &err); + if (err) { + error_propagate(errp, err); + return; + } prop->set(obj, value, errp); } @@ -1748,12 +1967,37 @@ void object_property_add_enum(Object *obj, const char *name, } } +void object_class_property_add_enum(ObjectClass *klass, const char *name, + const char *typename, + const char * const *strings, + int (*get)(Object *, Error **), + void (*set)(Object *, int, Error **), + Error **errp) +{ + Error *local_err = NULL; + EnumProperty *prop = g_malloc(sizeof(*prop)); + + prop->strings = strings; + prop->get = get; + prop->set = set; + + object_class_property_add(klass, name, typename, + get ? property_get_enum : NULL, + set ? property_set_enum : NULL, + property_release_enum, + prop, &local_err); + if (local_err) { + error_propagate(errp, local_err); + g_free(prop); + } +} + typedef struct TMProperty { void (*get)(Object *, struct tm *, Error **); } TMProperty; -static void property_get_tm(Object *obj, Visitor *v, void *opaque, - const char *name, Error **errp) +static void property_get_tm(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) { TMProperty *prop = opaque; Error *err = NULL; @@ -1764,31 +2008,31 @@ static void property_get_tm(Object *obj, Visitor *v, void *opaque, goto out; } - visit_start_struct(v, NULL, "struct tm", name, 0, &err); + visit_start_struct(v, name, NULL, 0, &err); if (err) { goto out; } - visit_type_int32(v, &value.tm_year, "tm_year", &err); + visit_type_int32(v, "tm_year", &value.tm_year, &err); if (err) { goto out_end; } - visit_type_int32(v, &value.tm_mon, "tm_mon", &err); + visit_type_int32(v, "tm_mon", &value.tm_mon, &err); if (err) { goto out_end; } - visit_type_int32(v, &value.tm_mday, "tm_mday", &err); + visit_type_int32(v, "tm_mday", &value.tm_mday, &err); if (err) { goto out_end; } - visit_type_int32(v, &value.tm_hour, "tm_hour", &err); + visit_type_int32(v, "tm_hour", &value.tm_hour, &err); if (err) { goto out_end; } - visit_type_int32(v, &value.tm_min, "tm_min", &err); + visit_type_int32(v, "tm_min", &value.tm_min, &err); if (err) { goto out_end; } - visit_type_int32(v, &value.tm_sec, "tm_sec", &err); + visit_type_int32(v, "tm_sec", &value.tm_sec, &err); if (err) { goto out_end; } @@ -1827,41 +2071,56 @@ void object_property_add_tm(Object *obj, const char *name, } } +void object_class_property_add_tm(ObjectClass *klass, const char *name, + void (*get)(Object *, struct tm *, Error **), + Error **errp) +{ + Error *local_err = NULL; + TMProperty *prop = g_malloc0(sizeof(*prop)); + + prop->get = get; + + object_class_property_add(klass, name, "struct tm", + get ? property_get_tm : NULL, NULL, + property_release_tm, + prop, &local_err); + if (local_err) { + error_propagate(errp, local_err); + g_free(prop); + } +} + static char *qdev_get_type(Object *obj, Error **errp) { return g_strdup(object_get_typename(obj)); } -static void property_get_uint8_ptr(Object *obj, Visitor *v, - void *opaque, const char *name, - Error **errp) +static void property_get_uint8_ptr(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) { uint8_t value = *(uint8_t *)opaque; - visit_type_uint8(v, &value, name, errp); + visit_type_uint8(v, name, &value, errp); } -static void property_get_uint16_ptr(Object *obj, Visitor *v, - void *opaque, const char *name, - Error **errp) +static void property_get_uint16_ptr(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) { uint16_t value = *(uint16_t *)opaque; - visit_type_uint16(v, &value, name, errp); + visit_type_uint16(v, name, &value, errp); } -static void property_get_uint32_ptr(Object *obj, Visitor *v, - void *opaque, const char *name, - Error **errp) +static void property_get_uint32_ptr(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) { uint32_t value = *(uint32_t *)opaque; - visit_type_uint32(v, &value, name, errp); + visit_type_uint32(v, name, &value, errp); } -static void property_get_uint64_ptr(Object *obj, Visitor *v, - void *opaque, const char *name, - Error **errp) +static void property_get_uint64_ptr(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) { uint64_t value = *(uint64_t *)opaque; - visit_type_uint64(v, &value, name, errp); + visit_type_uint64(v, name, &value, errp); } void object_property_add_uint8_ptr(Object *obj, const char *name, @@ -1871,6 +2130,13 @@ void object_property_add_uint8_ptr(Object *obj, const char *name, NULL, NULL, (void *)v, errp); } +void object_class_property_add_uint8_ptr(ObjectClass *klass, const char *name, + const uint8_t *v, Error **errp) +{ + object_class_property_add(klass, name, "uint8", property_get_uint8_ptr, + NULL, NULL, (void *)v, errp); +} + void object_property_add_uint16_ptr(Object *obj, const char *name, const uint16_t *v, Error **errp) { @@ -1878,6 +2144,13 @@ void object_property_add_uint16_ptr(Object *obj, const char *name, NULL, NULL, (void *)v, errp); } +void object_class_property_add_uint16_ptr(ObjectClass *klass, const char *name, + const uint16_t *v, Error **errp) +{ + object_class_property_add(klass, name, "uint16", property_get_uint16_ptr, + NULL, NULL, (void *)v, errp); +} + void object_property_add_uint32_ptr(Object *obj, const char *name, const uint32_t *v, Error **errp) { @@ -1885,6 +2158,13 @@ void object_property_add_uint32_ptr(Object *obj, const char *name, NULL, NULL, (void *)v, errp); } +void object_class_property_add_uint32_ptr(ObjectClass *klass, const char *name, + const uint32_t *v, Error **errp) +{ + object_class_property_add(klass, name, "uint32", property_get_uint32_ptr, + NULL, NULL, (void *)v, errp); +} + void object_property_add_uint64_ptr(Object *obj, const char *name, const uint64_t *v, Error **errp) { @@ -1892,21 +2172,28 @@ void object_property_add_uint64_ptr(Object *obj, const char *name, NULL, NULL, (void *)v, errp); } +void object_class_property_add_uint64_ptr(ObjectClass *klass, const char *name, + const uint64_t *v, Error **errp) +{ + object_class_property_add(klass, name, "uint64", property_get_uint64_ptr, + NULL, NULL, (void *)v, errp); +} + typedef struct { Object *target_obj; char *target_name; } AliasProperty; -static void property_get_alias(Object *obj, struct Visitor *v, void *opaque, - const char *name, Error **errp) +static void property_get_alias(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) { AliasProperty *prop = opaque; object_property_get(prop->target_obj, v, prop->target_name, errp); } -static void property_set_alias(Object *obj, struct Visitor *v, void *opaque, - const char *name, Error **errp) +static void property_set_alias(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) { AliasProperty *prop = opaque; @@ -1989,6 +2276,23 @@ void object_property_set_description(Object *obj, const char *name, op->description = g_strdup(description); } +void object_class_property_set_description(ObjectClass *klass, + const char *name, + const char *description, + Error **errp) +{ + ObjectProperty *op; + + op = g_hash_table_lookup(klass->properties, name); + if (!op) { + error_setg(errp, "Property '.%s' not found", name); + return; + } + + g_free(op->description); + op->description = g_strdup(description); +} + static void object_instance_init(Object *obj) { object_property_add_str(obj, "type", qdev_get_type, NULL, NULL); |