From: Alexander Barabash <alexander_barabash@mentor.com>
To: qemu-devel <qemu-devel@nongnu.org>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Subject: [Qemu-devel] [PATCH v2] Revised: Add object_property_get_child().
Date: Sun, 19 Feb 2012 18:04:06 +0200 [thread overview]
Message-ID: <4F411D76.9020105@mentor.com> (raw)
In-Reply-To: <4F40ECC6.8000603@mentor.com>
Add object_property_get_child().
Adding a direct accessor to a child property.
In the existing implementation, object_property_get() must be used,
with with a visitor, implementing the 'type_str' callback,
receiving the child's canonical path.
In the new implementation, the child is returned directly.
For link properties, object_property_get_link() is used
to resolve the link.
Also, in the new implementation, object_property_get_child() is used
as a subroutine of object_resolve_abs_path(). This changes the way
object_resolve_abs_path() operates, moving away from directly peeking
the property's 'opaque' field to using object_property_get_link().
Thus, in the mew implementation link properties are resolved in the
same way,
as they are when an absolute path is resolved.
Errors relevant to the operation, QERR_OBJECT_PROPERTY_NOT_FOUND
and QERR_OBJECT_PROPERTY_INVALID_TYPE were added.
Also, in the new implementation, some common sense refactoring was done
in the file 'qom/object.c' in the code extracting child and link
properties.
Signed-off-by: Alexander Barabash <alexander_barabash@mentor.com>
diff --git a/include/qemu/object.h b/include/qemu/object.h
index ba2409d..001521d 100644
--- a/include/qemu/object.h
+++ b/include/qemu/object.h
@@ -711,6 +711,21 @@ int64_t object_property_get_int(Object *obj, const
char *name,
struct Error **errp);
/**
+ * object_property_get_child:
+ * @obj: the object
+ * @name: the name of the property
+ * @errp: returns an error if this function fails
+ *
+ * Returns: if this a child property, the value of the property, or NULL if
+ * an error occurs (including when the property value is not a child
property).
+ *
+ * Result's reference count does not change.
+ * Therefore, he caller is responsible for referencing the result.
+ */
+Object *object_property_get_child(Object *obj, const char *name,
+ struct Error **errp);
+
+/**
* object_property_set:
* @obj: the object
* @v: the visitor that will be used to write the property value.
This should
diff --git a/qerror.h b/qerror.h
index e26c635..45e4468 100644
--- a/qerror.h
+++ b/qerror.h
@@ -178,6 +178,12 @@ QError *qobject_to_qerror(const QObject *obj);
#define QERR_NOT_SUPPORTED \
"{ 'class': 'NotSupported', 'data': {} }"
+#define QERR_OBJECT_PROPERTY_NOT_FOUND \
+ "{ 'class': 'ObjectPropertyNotFound', 'data': { 'object': %s,
'property': %s } }"
+
+#define QERR_OBJECT_PROPERTY_INVALID_TYPE \
+ "{ 'class': 'ObjectPropertyInvalidType', 'data': { 'object': %s,
'property': %s, 'expected_type': %s } }"
+
#define QERR_OPEN_FILE_FAILED \
"{ 'class': 'OpenFileFailed', 'data': { 'filename': %s } }"
diff --git a/qom/object.c b/qom/object.c
index 2de6eaf..ddd19e1 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -297,12 +297,64 @@ static void object_property_del_all(Object *obj)
}
}
+/*
+ * To ensure correct format checking,
+ * this function should be used only via REPORT_OBJECT_ERROR() macro.
+ *
+ * The first argument after 'obj' should be of type 'const char *'.
+ * It is ignored, and replaced by the canonical path of 'obj'.
+ */
+static void report_object_error(Error **errp, const char *fmt, Object
*obj, ...)
+ GCC_FMT_ATTR(2, 4);
+static void report_object_error(Error **errp, const char *fmt, Object
*obj, ...)
+{
+ gchar *path;
+ va_list ap;
+
+ if (errp != NULL) {
+ path = object_get_canonical_path(obj);
+ va_start(ap, obj);
+ va_arg(ap, const char *); /* Ignore the dummy string. */
+ error_set(errp, fmt, path, &ap);
+ va_end(ap);
+ g_free(path);
+ }
+}
+#define REPORT_OBJECT_ERROR(errp, fmt, obj, ...) \
+ do { \
+ report_object_error(errp, fmt, obj, "", ## __VA_ARGS__); \
+ } while (0)
+
+#define CHILD_PROPERTY_TYPE_PREFIX "child<"
+#define CHILD_PROPERTY_TYPE_SUFFIX ">"
+#define LINK_PROPERTY_TYPE_PREFIX "link<"
+#define LINK_PROPERTY_TYPE_SUFFIX ">"
+
+static bool object_property_is_child(ObjectProperty *prop)
+{
+ return (strstart(prop->type, CHILD_PROPERTY_TYPE_PREFIX, NULL) != 0);
+}
+
+static bool object_property_is_link(ObjectProperty *prop)
+{
+ return (strstart(prop->type, LINK_PROPERTY_TYPE_PREFIX, NULL) != 0);
+}
+
+/* Go from LINK_PROPERTY_TYPE_PREFIX FOO LINK_PROPERTY_TYPE_SUFFIX to
FOO. */
+static gchar *link_type_to_type(const gchar *type)
+{
+ return g_strndup(&type[sizeof(LINK_PROPERTY_TYPE_PREFIX) - 1],
+ strlen(type)
+ - (sizeof(LINK_PROPERTY_TYPE_PREFIX) - 1)
+ - (sizeof(LINK_PROPERTY_TYPE_SUFFIX) - 1));
+}
+
static void object_property_del_child(Object *obj, Object *child,
Error **errp)
{
ObjectProperty *prop;
QTAILQ_FOREACH(prop, &obj->properties, node) {
- if (!strstart(prop->type, "child<", NULL)) {
+ if (!object_property_is_child(prop)) {
continue;
}
@@ -799,6 +851,29 @@ Object *object_get_root(void)
return root;
}
+Object *object_property_get_child(Object *obj, const char *name,
+ struct Error **errp) {
+ Object *result;
+ ObjectProperty *prop = object_property_find(obj, name);
+
+ if (prop == NULL) {
+ REPORT_OBJECT_ERROR(errp, QERR_OBJECT_PROPERTY_NOT_FOUND, obj,
name);
+ return NULL;
+ }
+
+ if (object_property_is_child(prop)) {
+ result = (Object *)prop->opaque;
+ } else if (object_property_is_link(prop)) {
+ result = object_property_get_link(obj, name, errp);
+ } else {
+ result = NULL;
+ REPORT_OBJECT_ERROR(errp, QERR_OBJECT_PROPERTY_INVALID_TYPE,
+ obj, name, "child/link");
+ }
+
+ return result;
+}
+
static void object_get_child_property(Object *obj, Visitor *v, void
*opaque,
const char *name, Error **errp)
{
@@ -829,7 +904,10 @@ void object_property_add_child(Object *obj, const
char *name,
*/
assert(!object_is_type(obj, type_interface));
- type = g_strdup_printf("child<%s>",
object_get_typename(OBJECT(child)));
+ type = g_strdup_printf(CHILD_PROPERTY_TYPE_PREFIX
+ "%s"
+ CHILD_PROPERTY_TYPE_SUFFIX,
+ object_get_typename(OBJECT(child)));
object_property_add(obj, name, type, object_get_child_property,
NULL, object_finalize_child_property, child,
errp);
@@ -878,8 +956,7 @@ static void object_set_link_property(Object *obj,
Visitor *v, void *opaque,
if (strcmp(path, "") != 0) {
Object *target;
- /* Go from link<FOO> to FOO. */
- target_type = g_strndup(&type[5], strlen(type) - 6);
+ target_type = link_type_to_type(type);
target = object_resolve_path_type(path, target_type, &ambiguous);
if (ambiguous) {
@@ -907,7 +984,9 @@ void object_property_add_link(Object *obj, const
char *name,
{
gchar *full_type;
- full_type = g_strdup_printf("link<%s>", type);
+ full_type = g_strdup_printf(LINK_PROPERTY_TYPE_PREFIX
+ "%s"
+ LINK_PROPERTY_TYPE_SUFFIX, type);
object_property_add(obj, name, full_type,
object_get_link_property,
@@ -932,7 +1011,7 @@ gchar *object_get_canonical_path(Object *obj)
g_assert(obj->parent != NULL);
QTAILQ_FOREACH(prop, &obj->parent->properties, node) {
- if (!strstart(prop->type, "child<", NULL)) {
+ if (!object_property_is_child(prop)) {
continue;
}
@@ -964,7 +1043,6 @@ static Object *object_resolve_abs_path(Object *parent,
const char *typename,
int index)
{
- ObjectProperty *prop;
Object *child;
if (parts[index] == NULL) {
@@ -975,20 +1053,7 @@ static Object *object_resolve_abs_path(Object *parent,
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_property_get_child(parent, parts[index], NULL);
if (!child) {
return NULL;
@@ -1010,7 +1075,7 @@ static Object *object_resolve_partial_path(Object
*parent,
QTAILQ_FOREACH(prop, &parent->properties, node) {
Object *found;
- if (!strstart(prop->type, "child<", NULL)) {
+ if (!object_property_is_child(prop)) {
continue;
}
next prev parent reply other threads:[~2012-02-19 16:03 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-02-16 17:39 [Qemu-trivial] [PATCH] Add object_property_get_child() Alexander Barabash
2012-02-16 17:39 ` [Qemu-devel] " Alexander Barabash
2012-02-16 18:16 ` [Qemu-trivial] " Peter Maydell
2012-02-16 18:16 ` Peter Maydell
2012-02-17 10:17 ` [Qemu-trivial] " Paolo Bonzini
2012-02-17 10:17 ` [Qemu-devel] " Paolo Bonzini
2012-02-19 12:36 ` Alexander Barabash
2012-02-19 16:04 ` Alexander Barabash [this message]
2012-02-19 17:14 ` [Qemu-devel] [PATCH v2] Revised: " Andreas Färber
2012-02-19 18:30 ` Peter Maydell
2012-02-20 15:06 ` Alexander Barabash
2012-02-20 11:14 ` Alexander Barabash
2012-02-20 9:11 ` [Qemu-devel] [PATCH] " Paolo Bonzini
2012-02-20 11:13 ` Alexander Barabash
2012-02-20 11:33 ` Paolo Bonzini
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4F411D76.9020105@mentor.com \
--to=alexander_barabash@mentor.com \
--cc=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.