diff options
Diffstat (limited to 'include/qapi')
-rw-r--r-- | include/qapi/clone-visitor.h | 37 | ||||
-rw-r--r-- | include/qapi/visitor-impl.h | 14 | ||||
-rw-r--r-- | include/qapi/visitor.h | 66 |
3 files changed, 84 insertions, 33 deletions
diff --git a/include/qapi/clone-visitor.h b/include/qapi/clone-visitor.h new file mode 100644 index 0000000000..16ceff55dd --- /dev/null +++ b/include/qapi/clone-visitor.h @@ -0,0 +1,37 @@ +/* + * Clone Visitor + * + * Copyright (C) 2016 Red Hat, Inc. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#ifndef QAPI_CLONE_VISITOR_H +#define QAPI_CLONE_VISITOR_H + +#include "qapi/visitor.h" + +/* + * The clone visitor is for direct use only by the QAPI_CLONE() macro; + * it requires that the root visit occur on an object, list, or + * alternate, and is not usable directly on built-in QAPI types. + */ +typedef struct QapiCloneVisitor QapiCloneVisitor; + +void *qapi_clone(const void *src, void (*visit_type)(Visitor *, const char *, + void **, Error **)); + +/* + * Deep-clone QAPI object @src of the given @type, and return the result. + * + * Not usable on QAPI scalars (integers, strings, enums), nor on a + * QAPI object that references the 'any' type. Safe when @src is NULL. + */ +#define QAPI_CLONE(type, src) \ + ((type *)qapi_clone(src, \ + (void (*)(Visitor *, const char *, void**, \ + Error **))visit_type_ ## type)) + +#endif diff --git a/include/qapi/visitor-impl.h b/include/qapi/visitor-impl.h index 16e0b86d57..8bd47ee4bb 100644 --- a/include/qapi/visitor-impl.h +++ b/include/qapi/visitor-impl.h @@ -27,14 +27,18 @@ */ /* - * There are three classes of visitors; setting the class determines + * There are four classes of visitors; setting the class determines * how QAPI enums are visited, as well as what additional restrictions - * can be asserted. + * can be asserted. The values are intentionally chosen so as to + * permit some assertions based on whether a given bit is set (that + * is, some assertions apply to input and clone visitors, some + * assertions apply to output and clone visitors). */ typedef enum VisitorType { - VISITOR_INPUT, - VISITOR_OUTPUT, - VISITOR_DEALLOC, + VISITOR_INPUT = 1, + VISITOR_OUTPUT = 2, + VISITOR_CLONE = 3, + VISITOR_DEALLOC = 4, } VisitorType; struct Visitor diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h index 00a60eaaab..fb8f4eb6ec 100644 --- a/include/qapi/visitor.h +++ b/include/qapi/visitor.h @@ -24,15 +24,16 @@ * for doing work at each node of a QAPI graph; it can also be used * for a virtual walk, where there is no actual QAPI C struct. * - * There are three kinds of visitor classes: input visitors (QMP, + * There are four kinds of visitor classes: input visitors (QMP, * string, and QemuOpts) parse an external representation and build * the corresponding QAPI graph, output visitors (QMP and string) take - * a completed QAPI graph and generate an external representation, and - * the dealloc visitor can take a QAPI graph (possibly partially - * constructed) and recursively free its resources. While the dealloc - * and QMP input/output visitors are general, the string and QemuOpts - * visitors have some implementation limitations; see the - * documentation for each visitor for more details on what it + * a completed QAPI graph and generate an external representation, the + * dealloc visitor can take a QAPI graph (possibly partially + * constructed) and recursively free its resources, and the clone + * visitor performs a deep clone of one QAPI object to another. While + * the dealloc and QMP input/output visitors are general, the string, + * QemuOpts, and clone visitors have some implementation limitations; + * see the documentation for each visitor for more details on what it * supports. Also, see visitor-impl.h for the callback contracts * implemented by each visitor, and docs/qapi-code-gen.txt for more * about the QAPI code generator. @@ -80,9 +81,9 @@ * * If an error is detected during visit_type_FOO() with an input * visitor, then *@obj will be NULL for pointer types, and left - * unchanged for scalar types. Using an output visitor with an - * incomplete object has undefined behavior (other than a special case - * for visit_type_str() treating NULL like ""), while the dealloc + * unchanged for scalar types. Using an output or clone visitor with + * an incomplete object has undefined behavior (other than a special + * case for visit_type_str() treating NULL like ""), while the dealloc * visitor safely handles incomplete objects. Since input visitors * never produce an incomplete object, such an object is possible only * by manual construction. @@ -102,11 +103,19 @@ * * void qapi_free_FOO(FOO *obj); * - * which behaves like free() in that @obj may be NULL. Because of - * these functions, the dealloc visitor is seldom used directly - * outside of generated code. QAPI types can also inherit from a base - * class; when this happens, a function is generated for easily going - * from the derived type to the base type: + * where behaves like free() in that @obj may be NULL. Such objects + * may also be used with the following macro, provided alongside the + * clone visitor: + * + * Type *QAPI_CLONE(Type, src); + * + * in order to perform a deep clone of @src. Because of the generated + * qapi_free functions and the QAPI_CLONE() macro, the clone and + * dealloc visitor should not be used directly outside of QAPI code. + * + * QAPI types can also inherit from a base class; when this happens, a + * function is generated for easily going from the derived type to the + * base type: * * BASE *qapi_CHILD_base(CHILD *obj); * @@ -272,9 +281,9 @@ void visit_free(Visitor *v); * container; see the general description of @name above. * * @obj must be non-NULL for a real walk, in which case @size - * determines how much memory an input visitor will allocate into - * *@obj. @obj may also be NULL for a virtual walk, in which case - * @size is ignored. + * determines how much memory an input or clone visitor will allocate + * into *@obj. @obj may also be NULL for a virtual walk, in which + * case @size is ignored. * * @errp obeys typical error usage, and reports failures such as a * member @name is not present, or present but not an object. On @@ -327,9 +336,9 @@ void visit_end_struct(Visitor *v, void **obj); * container; see the general description of @name above. * * @list must be non-NULL for a real walk, in which case @size - * determines how much memory an input visitor will allocate into - * *@list (at least sizeof(GenericList)). Some visitors also allow - * @list to be NULL for a virtual walk, in which case @size is + * determines how much memory an input or clone visitor will allocate + * into *@list (at least sizeof(GenericList)). Some visitors also + * allow @list to be NULL for a virtual walk, in which case @size is * ignored. * * @errp obeys typical error usage, and reports failures such as a @@ -386,10 +395,10 @@ void visit_end_list(Visitor *v, void **list); * @name expresses the relationship of this alternate to its parent * container; see the general description of @name above. * - * @obj must not be NULL. Input visitors use @size to determine how - * much memory to allocate into *@obj, then determine the qtype of the - * next thing to be visited, stored in (*@obj)->type. Other visitors - * will leave @obj unchanged. + * @obj must not be NULL. Input and clone visitors use @size to + * determine how much memory to allocate into *@obj, then determine + * the qtype of the next thing to be visited, stored in (*@obj)->type. + * Other visitors will leave @obj unchanged. * * If @promote_int, treat integers as QTYPE_FLOAT. * @@ -554,9 +563,10 @@ void visit_type_bool(Visitor *v, const char *name, bool *obj, Error **errp); * @name expresses the relationship of this string to its parent * container; see the general description of @name above. * - * @obj must be non-NULL. Input visitors set *@obj to the value - * (never NULL). Other visitors leave *@obj unchanged, and commonly - * treat NULL like "". + * @obj must be non-NULL. Input and clone visitors set *@obj to the + * value (always using "" rather than NULL for an empty string). + * Other visitors leave *@obj unchanged, and commonly treat NULL like + * "". * * It is safe to cast away const when preparing a (const char *) value * into @obj for use by an output visitor. |