Commit adfb264c authored by Eric Blake's avatar Eric Blake Committed by Markus Armbruster
Browse files

qapi: Document visitor interfaces, add assertions



The visitor interface for mapping between QObject/QemuOpts/string
and QAPI is scandalously under-documented, making changes to visitor
core, individual visitors, and users of visitors difficult to
coordinate.  Among other questions: when is it safe to pass NULL,
vs. when a string must be provided; which visitors implement which
callbacks; the difference between concrete and virtual visits.

Correct this by retrofitting proper contracts, and document where some
of the interface warts remain (for example, we may want to modify
visit_end_* to require the same 'obj' as the visit_start counterpart,
so the dealloc visitor can be simplified).  Later patches in this
series will tackle some, but not all, of these warts.

Add assertions to (partially) enforce the contract.  Some of these
were only made possible by recent cleanup commits.

Signed-off-by: default avatarEric Blake <eblake@redhat.com>
Message-Id: <1461879932-9020-13-git-send-email-eblake@redhat.com>
[Doc fix from Eric squashed in]
Signed-off-by: default avatarMarkus Armbruster <armbru@redhat.com>
parent fcf3cb21
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -18,6 +18,11 @@

typedef struct QapiDeallocVisitor QapiDeallocVisitor;

/*
 * The dealloc visitor is primarly used only by generated
 * qapi_free_FOO() functions, and is the only visitor designed to work
 * correctly in the face of a partially-constructed QAPI tree.
 */
QapiDeallocVisitor *qapi_dealloc_visitor_new(void);
void qapi_dealloc_visitor_cleanup(QapiDeallocVisitor *d);

+3 −0
Original line number Diff line number Diff line
@@ -29,6 +29,9 @@ typedef struct OptsVisitor OptsVisitor;
 * - string representations of negative numbers yield negative values,
 * - values below INT64_MIN or LLONG_MIN are rejected,
 * - values above INT64_MAX or LLONG_MAX are rejected.
 *
 * The Opts input visitor does not implement support for visiting QAPI
 * alternates, numbers (other than integers), or arbitrary QTypes.
 */
OptsVisitor *opts_visitor_new(const QemuOpts *opts);
void opts_visitor_cleanup(OptsVisitor *nv);
+4 −0
Original line number Diff line number Diff line
@@ -17,6 +17,10 @@

typedef struct StringInputVisitor StringInputVisitor;

/*
 * The string input visitor does not implement support for visiting
 * QAPI structs, alternates, or arbitrary QTypes.
 */
StringInputVisitor *string_input_visitor_new(const char *str);
void string_input_visitor_cleanup(StringInputVisitor *v);

+4 −0
Original line number Diff line number Diff line
@@ -17,6 +17,10 @@

typedef struct StringOutputVisitor StringOutputVisitor;

/*
 * The string output visitor does not implement support for visiting
 * QAPI structs, alternates, or arbitrary QTypes.
 */
StringOutputVisitor *string_output_visitor_new(bool human);
void string_output_visitor_cleanup(StringOutputVisitor *v);

+36 −8
Original line number Diff line number Diff line
@@ -14,6 +14,18 @@

#include "qapi/visitor.h"

/*
 * This file describes the callback interface for implementing a QAPI
 * visitor.  For the client interface, see visitor.h.  When
 * implementing the callbacks, it is easiest to declare a struct with
 * 'Visitor visitor;' as the first member.  A callback's contract
 * matches the corresponding public functions' contract unless stated
 * otherwise.  In the comments below, some callbacks are marked "must
 * be set for $TYPE visits to work"; if a visitor implementation omits
 * that callback, it should also document that it is only useful for a
 * subset of QAPI.
 */

/*
 * There are three classes of visitors; setting the class determines
 * how QAPI enums are visited, as well as what additional restrictions
@@ -27,43 +39,59 @@ typedef enum VisitorType {

struct Visitor
{
    /* Must be set */
    /* Must be set to visit structs */
    void (*start_struct)(Visitor *v, const char *name, void **obj,
                         size_t size, Error **errp);

    /* Must be set to visit structs */
    void (*end_struct)(Visitor *v, Error **errp);

    /* Must be set */
    void (*start_list)(Visitor *v, const char *name, Error **errp);

    /* Must be set */
    GenericList *(*next_list)(Visitor *v, GenericList **list, size_t size);

    /* Must be set */
    void (*end_list)(Visitor *v);

    /* Optional, needed for input and dealloc visitors.  */
    /* Must be set by input and dealloc visitors to visit alternates;
     * optional for output visitors. */
    void (*start_alternate)(Visitor *v, const char *name,
                            GenericAlternate **obj, size_t size,
                            bool promote_int, Error **errp);

    /* Optional, needed for dealloc visitor.  */
    /* Optional, needed for dealloc visitor */
    void (*end_alternate)(Visitor *v);

    /* Must be set. */
    /* Must be set */
    void (*type_int64)(Visitor *v, const char *name, int64_t *obj,
                       Error **errp);
    /* Must be set. */

    /* Must be set */
    void (*type_uint64)(Visitor *v, const char *name, uint64_t *obj,
                        Error **errp);
    /* Optional; fallback is type_uint64().  */

    /* Optional; fallback is type_uint64() */
    void (*type_size)(Visitor *v, const char *name, uint64_t *obj,
                      Error **errp);
    /* Must be set. */

    /* Must be set */
    void (*type_bool)(Visitor *v, const char *name, bool *obj, Error **errp);

    /* Must be set */
    void (*type_str)(Visitor *v, const char *name, char **obj, Error **errp);

    /* Must be set to visit numbers */
    void (*type_number)(Visitor *v, const char *name, double *obj,
                        Error **errp);

    /* Must be set to visit arbitrary QTypes */
    void (*type_any)(Visitor *v, const char *name, QObject **obj,
                     Error **errp);

    /* May be NULL; most useful for input visitors. */
    /* Must be set for input visitors, optional otherwise.  The core
     * takes care of the return type in the public interface. */
    void (*optional)(Visitor *v, const char *name, bool *present);

    /* Must be set */
Loading