Add this sister helper besides object_child_foreach_recursive() to loop over child objects only if the object can be casted to a specific type.
Suggested-by: Michael S. Tsirkin <m...@redhat.com> Signed-off-by: Peter Xu <pet...@redhat.com> --- include/qom/object.h | 20 ++++++++++++++++++++ qom/object.c | 27 +++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/include/qom/object.h b/include/qom/object.h index faae0d841f..355277db40 100644 --- a/include/qom/object.h +++ b/include/qom/object.h @@ -1926,6 +1926,26 @@ int object_child_foreach(Object *obj, int (*fn)(Object *child, void *opaque), int object_child_foreach_recursive(Object *obj, int (*fn)(Object *child, void *opaque), void *opaque); + +/** + * object_child_foreach_recursive_type: + * @obj: the object whose children will be navigated + * @type: the typename string to scan + * @fn: the iterator function to be called + * @opaque: an opaque value that will be passed to the iterator + * + * This is a special version of object_child_foreach_recursive() so that we + * only call the fn() if the child can be casted to the @typename specified. + * Please refer to the comments above object_child_foreach_recursive() for + * more details. + * + * Returns: The last value returned by @fn, or 0 if there is no child. + */ +int object_child_foreach_recursive_type(Object *obj, + const char *typename, + int (*fn)(Object *child, void *opaque), + void *opaque); + /** * container_get: * @root: root of the #path, e.g., object_get_root() diff --git a/qom/object.c b/qom/object.c index 6be710bc40..d25ca09b1d 100644 --- a/qom/object.c +++ b/qom/object.c @@ -1134,6 +1134,33 @@ int object_child_foreach_recursive(Object *obj, return do_object_child_foreach(obj, fn, opaque, true); } +typedef struct { + const char *typename; + int (*fn)(Object *child, void *opaque); + void *opaque; +} ObjectTypeArgs; + +static int object_child_hook(Object *child, void *opaque) +{ + ObjectTypeArgs *args = opaque; + + if (object_dynamic_cast(child, args->typename)) { + return args->fn(child, args->opaque); + } + + return 0; +} + +int object_child_foreach_recursive_type(Object *obj, + const char *typename, + int (*fn)(Object *child, void *opaque), + void *opaque) +{ + ObjectTypeArgs args = { .typename = typename, .fn = fn, .opaque = opaque }; + + return object_child_foreach_recursive(obj, object_child_hook, &args); +} + static void object_class_get_list_tramp(ObjectClass *klass, void *opaque) { GSList **list = opaque; -- 2.32.0