* 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"
#include "qom/qom-qobject.h"
#include "qapi/qmp/qobject.h"
#include "qapi/qmp/qbool.h"
-#include "qapi/qmp/qint.h"
#include "qapi/qmp/qstring.h"
#define MAX_INTERFACES 32
return 0;
}
+size_t object_type_get_instance_size(const char *typename)
+{
+ TypeImpl *type = type_get_by_name(typename);
+
+ g_assert(type != NULL);
+ return type_object_get_size(type);
+}
+
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;
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;
ti->class_size = type_class_get_size(ti);
ti->instance_size = type_object_get_size(ti);
+ /* Any type with zero instance_size is implicitly abstract.
+ * This means interface types are all abstract.
+ */
+ if (ti->instance_size == 0) {
+ ti->abstract = true;
+ }
ti->class = g_malloc0(ti->class_size);
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;
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;
}
}
-void object_initialize_with_type(void *data, size_t size, TypeImpl *type)
+static void object_initialize_with_type(void *data, size_t size, TypeImpl *type)
{
Object *obj = data;
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);
}
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) {
- object_property_del(obj, prop->name, errp);
+ 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) {
+ g_hash_table_iter_remove(&iter);
break;
}
}
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);
}
}
-Object *object_new_with_type(Type type)
+static Object *object_new_with_type(Type type)
{
Object *obj;
return obj;
error:
- if (local_err) {
- error_propagate(errp, local_err);
- }
+ error_propagate(errp, local_err);
object_unref(obj);
return NULL;
}
Object *inst;
for (i = 0; obj && i < OBJECT_CLASS_CAST_CACHE; i++) {
- if (obj->class->object_cast_cache[i] == typename) {
+ if (atomic_read(&obj->class->object_cast_cache[i]) == typename) {
goto out;
}
}
if (obj && obj == inst) {
for (i = 1; i < OBJECT_CLASS_CAST_CACHE; i++) {
- obj->class->object_cast_cache[i - 1] =
- obj->class->object_cast_cache[i];
+ atomic_set(&obj->class->object_cast_cache[i - 1],
+ atomic_read(&obj->class->object_cast_cache[i]));
}
- obj->class->object_cast_cache[i - 1] = typename;
+ atomic_set(&obj->class->object_cast_cache[i - 1], typename);
}
out:
int i;
for (i = 0; class && i < OBJECT_CLASS_CAST_CACHE; i++) {
- if (class->class_cast_cache[i] == typename) {
+ if (atomic_read(&class->class_cast_cache[i]) == typename) {
ret = class;
goto out;
}
#ifdef CONFIG_QOM_CAST_DEBUG
if (class && ret == class) {
for (i = 1; i < OBJECT_CLASS_CAST_CACHE; i++) {
- class->class_cast_cache[i - 1] = class->class_cast_cache[i];
+ atomic_set(&class->class_cast_cache[i - 1],
+ atomic_read(&class->class_cast_cache[i]));
}
- class->class_cast_cache[i - 1] = typename;
+ atomic_set(&class->class_cast_cache[i - 1], typename);
}
out:
#endif
return ret;
}
-const char *object_get_typename(Object *obj)
+const char *object_get_typename(const Object *obj)
{
return obj->class->type->name;
}
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;
if (!obj) {
return;
}
- atomic_inc(&obj->ref);
+ atomic_inc(&obj->ref);
}
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) {
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));
+
+ 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(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->release = release;
prop->opaque = opaque;
- QTAILQ_INSERT_TAIL(&obj->properties, prop, node);
+ g_hash_table_insert(klass->properties, g_strdup(name), prop);
+
return prop;
}
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,
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);
}
}
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);
}
}
retval = g_strdup(qstring_get_str(qstring));
}
- QDECREF(qstring);
+ qobject_decref(ret);
return retval;
}
retval = qbool_get_bool(qbool);
}
- QDECREF(qbool);
+ qobject_decref(ret);
return retval;
}
void object_property_set_int(Object *obj, int64_t value,
const char *name, Error **errp)
{
- QInt *qint = qint_from_int(value);
- object_property_set_qobject(obj, QOBJECT(qint), name, errp);
+ QNum *qnum = qnum_from_int(value);
+ object_property_set_qobject(obj, QOBJECT(qnum), name, errp);
- QDECREF(qint);
+ QDECREF(qnum);
}
int64_t object_property_get_int(Object *obj, const char *name,
Error **errp)
{
QObject *ret = object_property_get_qobject(obj, name, errp);
- QInt *qint;
+ QNum *qnum;
int64_t retval;
if (!ret) {
return -1;
}
- qint = qobject_to_qint(ret);
- if (!qint) {
+
+ qnum = qobject_to_qnum(ret);
+ if (!qnum || !qnum_get_try_int(qnum, &retval)) {
error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, "int");
retval = -1;
- } else {
- retval = qint_get_int(qint);
}
- QDECREF(qint);
+ qobject_decref(ret);
+ return retval;
+}
+
+void object_property_set_uint(Object *obj, uint64_t value,
+ const char *name, Error **errp)
+{
+ QNum *qnum = qnum_from_uint(value);
+
+ object_property_set_qobject(obj, QOBJECT(qnum), name, errp);
+ QDECREF(qnum);
+}
+
+uint64_t object_property_get_uint(Object *obj, const char *name,
+ Error **errp)
+{
+ QObject *ret = object_property_get_qobject(obj, name, errp);
+ QNum *qnum;
+ uint64_t retval;
+
+ if (!ret) {
+ return 0;
+ }
+ qnum = qobject_to_qnum(ret);
+ if (!qnum || !qnum_get_try_uint(qnum, &retval)) {
+ error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, "uint");
+ retval = 0;
+ }
+
+ qobject_decref(ret);
return retval;
}
int object_property_get_enum(Object *obj, const char *name,
const char *typename, Error **errp)
{
- StringOutputVisitor *sov;
- StringInputVisitor *siv;
+ Error *err = NULL;
+ Visitor *v;
char *str;
int ret;
ObjectProperty *prop = object_property_find(obj, name, errp);
enumprop = prop->opaque;
- sov = string_output_visitor_new(false);
- object_property_get(obj, string_output_get_visitor(sov), name, errp);
- 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);
+ v = string_output_visitor_new(false, &str);
+ object_property_get(obj, v, name, &err);
+ if (err) {
+ error_propagate(errp, err);
+ visit_free(v);
+ return 0;
+ }
+ visit_complete(v, &str);
+ visit_free(v);
+ v = string_input_visitor_new(str);
+ visit_type_enum(v, name, &ret, enumprop->strings, errp);
g_free(str);
- string_input_visitor_cleanup(siv);
+ visit_free(v);
return ret;
}
void object_property_get_uint16List(Object *obj, const char *name,
uint16List **list, Error **errp)
{
- StringOutputVisitor *ov;
- StringInputVisitor *iv;
+ Error *err = NULL;
+ Visitor *v;
char *str;
- ov = string_output_visitor_new(false);
- object_property_get(obj, string_output_get_visitor(ov),
- name, errp);
- str = string_output_get_string(ov);
- iv = string_input_visitor_new(str);
- visit_type_uint16List(string_input_get_visitor(iv),
- list, NULL, errp);
+ v = string_output_visitor_new(false, &str);
+ object_property_get(obj, v, name, &err);
+ if (err) {
+ error_propagate(errp, err);
+ goto out;
+ }
+ visit_complete(v, &str);
+ visit_free(v);
+ v = string_input_visitor_new(str);
+ visit_type_uint16List(v, NULL, list, errp);
g_free(str);
- string_output_visitor_cleanup(ov);
- string_input_visitor_cleanup(iv);
+out:
+ visit_free(v);
}
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);
+ Visitor *v = string_input_visitor_new(string);
+ object_property_set(obj, v, name, errp);
+ visit_free(v);
}
char *object_property_print(Object *obj, const char *name, bool human,
Error **errp)
{
- StringOutputVisitor *mo;
+ Visitor *v;
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);
+ v = string_output_visitor_new(human, &string);
+ object_property_get(obj, v, name, &local_err);
if (local_err) {
error_propagate(errp, local_err);
goto out;
}
- string = string_output_get_string(mo);
+ visit_complete(v, &string);
out:
- string_output_visitor_cleanup(mo);
+ visit_free(v);
return string;
}
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);
}
g_free(type);
}
-void object_property_allow_set_link(Object *obj, const char *name,
+void object_property_allow_set_link(const Object *obj, const char *name,
Object *val, Error **errp)
{
/* Allow the link to be set, always */
typedef struct {
Object **child;
- void (*check)(Object *, const char *, Object *, Error **);
+ void (*check)(const Object *, const char *, Object *, Error **);
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;
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);
}
}
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) {
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;
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);
void object_property_add_link(Object *obj, const char *name,
const char *type, Object **child,
- void (*check)(Object *, const char *,
+ void (*check)(const Object *, const char *,
Object *, Error **),
ObjectPropertyLinkFlags flags,
Error **errp)
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;
}
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)) {
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;
}
}
+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, errp);
- visit_type_bool(v, &value, name, errp);
+ value = prop->get(obj, &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
+
+ 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;
}
}
-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, &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
- value = prop->get(obj, errp);
- visit_type_enum(v, &value, prop->strings, NULL, name, errp);
+ 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);
}
}
}
+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;
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;
}
+ visit_check_struct(v, &err);
out_end:
- error_propagate(errp, err);
- err = NULL;
- visit_end_struct(v, errp);
+ visit_end_struct(v, NULL);
out:
error_propagate(errp, err);
}
}
+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,
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)
{
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)
{
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)
{
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;
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);