xref: /qemu/qapi/qapi-clone-visitor.c (revision 54e91d1523b412b4cff7cb36c898fa9dc133e886)
1a15fcc3cSEric Blake /*
2a15fcc3cSEric Blake  * Copy one QAPI object to another
3a15fcc3cSEric Blake  *
4a15fcc3cSEric Blake  * Copyright (C) 2016 Red Hat, Inc.
5a15fcc3cSEric Blake  *
6a15fcc3cSEric Blake  * This work is licensed under the terms of the GNU GPL, version 2 or later.
7a15fcc3cSEric Blake  * See the COPYING file in the top-level directory.
8a15fcc3cSEric Blake  *
9a15fcc3cSEric Blake  */
10a15fcc3cSEric Blake 
11a15fcc3cSEric Blake #include "qemu/osdep.h"
12a15fcc3cSEric Blake #include "qapi/clone-visitor.h"
13a15fcc3cSEric Blake #include "qapi/visitor-impl.h"
14a15fcc3cSEric Blake #include "qapi/error.h"
15*407bc4bfSDaniel P. Berrangé #include "qobject/qnull.h"
16a15fcc3cSEric Blake 
17a15fcc3cSEric Blake struct QapiCloneVisitor {
18a15fcc3cSEric Blake     Visitor visitor;
19a15fcc3cSEric Blake     size_t depth;
20a15fcc3cSEric Blake };
21a15fcc3cSEric Blake 
to_qcv(Visitor * v)22a15fcc3cSEric Blake static QapiCloneVisitor *to_qcv(Visitor *v)
23a15fcc3cSEric Blake {
24a15fcc3cSEric Blake     return container_of(v, QapiCloneVisitor, visitor);
25a15fcc3cSEric Blake }
26a15fcc3cSEric Blake 
qapi_clone_start_struct(Visitor * v,const char * name,void ** obj,size_t size,Error ** errp)27012d4c96SMarkus Armbruster static bool qapi_clone_start_struct(Visitor *v, const char *name, void **obj,
28a15fcc3cSEric Blake                                     size_t size, Error **errp)
29a15fcc3cSEric Blake {
30a15fcc3cSEric Blake     QapiCloneVisitor *qcv = to_qcv(v);
31a15fcc3cSEric Blake 
32a15fcc3cSEric Blake     if (!obj) {
33a15fcc3cSEric Blake         assert(qcv->depth);
34a15fcc3cSEric Blake         /* Only possible when visiting an alternate's object
35a15fcc3cSEric Blake          * branch. Nothing further to do here, since the earlier
36a15fcc3cSEric Blake          * visit_start_alternate() already copied memory. */
37012d4c96SMarkus Armbruster         return true;
38a15fcc3cSEric Blake     }
39a15fcc3cSEric Blake 
40a15fcc3cSEric Blake     *obj = g_memdup(*obj, size);
41a15fcc3cSEric Blake     qcv->depth++;
42012d4c96SMarkus Armbruster     return true;
43a15fcc3cSEric Blake }
44a15fcc3cSEric Blake 
qapi_clone_end(Visitor * v,void ** obj)45a15fcc3cSEric Blake static void qapi_clone_end(Visitor *v, void **obj)
46a15fcc3cSEric Blake {
47a15fcc3cSEric Blake     QapiCloneVisitor *qcv = to_qcv(v);
48a15fcc3cSEric Blake 
49a15fcc3cSEric Blake     assert(qcv->depth);
50a15fcc3cSEric Blake     if (obj) {
51a15fcc3cSEric Blake         qcv->depth--;
52a15fcc3cSEric Blake     }
53a15fcc3cSEric Blake }
54a15fcc3cSEric Blake 
qapi_clone_start_list(Visitor * v,const char * name,GenericList ** listp,size_t size,Error ** errp)55012d4c96SMarkus Armbruster static bool qapi_clone_start_list(Visitor *v, const char *name,
56a15fcc3cSEric Blake                                   GenericList **listp, size_t size,
57a15fcc3cSEric Blake                                   Error **errp)
58a15fcc3cSEric Blake {
59012d4c96SMarkus Armbruster     return qapi_clone_start_struct(v, name, (void **)listp, size, errp);
60a15fcc3cSEric Blake }
61a15fcc3cSEric Blake 
qapi_clone_next_list(Visitor * v,GenericList * tail,size_t size)62a15fcc3cSEric Blake static GenericList *qapi_clone_next_list(Visitor *v, GenericList *tail,
63a15fcc3cSEric Blake                                          size_t size)
64a15fcc3cSEric Blake {
65a15fcc3cSEric Blake     QapiCloneVisitor *qcv = to_qcv(v);
66a15fcc3cSEric Blake 
67a15fcc3cSEric Blake     assert(qcv->depth);
68a15fcc3cSEric Blake     /* Unshare the tail of the list cloned by g_memdup() */
69a15fcc3cSEric Blake     tail->next = g_memdup(tail->next, size);
70a15fcc3cSEric Blake     return tail->next;
71a15fcc3cSEric Blake }
72a15fcc3cSEric Blake 
qapi_clone_start_alternate(Visitor * v,const char * name,GenericAlternate ** obj,size_t size,Error ** errp)73012d4c96SMarkus Armbruster static bool qapi_clone_start_alternate(Visitor *v, const char *name,
74a15fcc3cSEric Blake                                        GenericAlternate **obj, size_t size,
7560390d2dSMarc-André Lureau                                        Error **errp)
76a15fcc3cSEric Blake {
77012d4c96SMarkus Armbruster     return qapi_clone_start_struct(v, name, (void **)obj, size, errp);
78a15fcc3cSEric Blake }
79a15fcc3cSEric Blake 
qapi_clone_type_int64(Visitor * v,const char * name,int64_t * obj,Error ** errp)80012d4c96SMarkus Armbruster static bool qapi_clone_type_int64(Visitor *v, const char *name, int64_t *obj,
81a15fcc3cSEric Blake                                   Error **errp)
82a15fcc3cSEric Blake {
83a15fcc3cSEric Blake     QapiCloneVisitor *qcv = to_qcv(v);
84a15fcc3cSEric Blake 
85a15fcc3cSEric Blake     assert(qcv->depth);
86a15fcc3cSEric Blake     /* Value was already cloned by g_memdup() */
87012d4c96SMarkus Armbruster     return true;
88a15fcc3cSEric Blake }
89a15fcc3cSEric Blake 
qapi_clone_type_uint64(Visitor * v,const char * name,uint64_t * obj,Error ** errp)90012d4c96SMarkus Armbruster static bool qapi_clone_type_uint64(Visitor *v, const char *name,
91a15fcc3cSEric Blake                                    uint64_t *obj, Error **errp)
92a15fcc3cSEric Blake {
93a15fcc3cSEric Blake     QapiCloneVisitor *qcv = to_qcv(v);
94a15fcc3cSEric Blake 
95a15fcc3cSEric Blake     assert(qcv->depth);
96a15fcc3cSEric Blake     /* Value was already cloned by g_memdup() */
97012d4c96SMarkus Armbruster     return true;
98a15fcc3cSEric Blake }
99a15fcc3cSEric Blake 
qapi_clone_type_bool(Visitor * v,const char * name,bool * obj,Error ** errp)100012d4c96SMarkus Armbruster static bool qapi_clone_type_bool(Visitor *v, const char *name, bool *obj,
101a15fcc3cSEric Blake                                  Error **errp)
102a15fcc3cSEric Blake {
103a15fcc3cSEric Blake     QapiCloneVisitor *qcv = to_qcv(v);
104a15fcc3cSEric Blake 
105a15fcc3cSEric Blake     assert(qcv->depth);
106a15fcc3cSEric Blake     /* Value was already cloned by g_memdup() */
107012d4c96SMarkus Armbruster     return true;
108a15fcc3cSEric Blake }
109a15fcc3cSEric Blake 
qapi_clone_type_str(Visitor * v,const char * name,char ** obj,Error ** errp)110012d4c96SMarkus Armbruster static bool qapi_clone_type_str(Visitor *v, const char *name, char **obj,
111a15fcc3cSEric Blake                                 Error **errp)
112a15fcc3cSEric Blake {
113a15fcc3cSEric Blake     QapiCloneVisitor *qcv = to_qcv(v);
114a15fcc3cSEric Blake 
115a15fcc3cSEric Blake     assert(qcv->depth);
116a15fcc3cSEric Blake     /*
117a15fcc3cSEric Blake      * Pointer was already cloned by g_memdup; create fresh copy.
118b3db211fSDaniel P. Berrange      * Note that as long as qobject-output-visitor accepts NULL instead of
119a15fcc3cSEric Blake      * "", then we must do likewise. However, we want to obey the
120a15fcc3cSEric Blake      * input visitor semantics of never producing NULL when the empty
121a15fcc3cSEric Blake      * string is intended.
122a15fcc3cSEric Blake      */
123a15fcc3cSEric Blake     *obj = g_strdup(*obj ?: "");
124012d4c96SMarkus Armbruster     return true;
125a15fcc3cSEric Blake }
126a15fcc3cSEric Blake 
qapi_clone_type_number(Visitor * v,const char * name,double * obj,Error ** errp)127012d4c96SMarkus Armbruster static bool qapi_clone_type_number(Visitor *v, const char *name, double *obj,
128a15fcc3cSEric Blake                                    Error **errp)
129a15fcc3cSEric Blake {
130a15fcc3cSEric Blake     QapiCloneVisitor *qcv = to_qcv(v);
131a15fcc3cSEric Blake 
132a15fcc3cSEric Blake     assert(qcv->depth);
133a15fcc3cSEric Blake     /* Value was already cloned by g_memdup() */
134012d4c96SMarkus Armbruster     return true;
135a15fcc3cSEric Blake }
136a15fcc3cSEric Blake 
qapi_clone_type_null(Visitor * v,const char * name,QNull ** obj,Error ** errp)137012d4c96SMarkus Armbruster static bool qapi_clone_type_null(Visitor *v, const char *name, QNull **obj,
138d2f95f4dSMarkus Armbruster                                  Error **errp)
139a15fcc3cSEric Blake {
140a15fcc3cSEric Blake     QapiCloneVisitor *qcv = to_qcv(v);
141a15fcc3cSEric Blake 
142a15fcc3cSEric Blake     assert(qcv->depth);
143d2f95f4dSMarkus Armbruster     *obj = qnull();
144012d4c96SMarkus Armbruster     return true;
145a15fcc3cSEric Blake }
146a15fcc3cSEric Blake 
qapi_clone_free(Visitor * v)147a15fcc3cSEric Blake static void qapi_clone_free(Visitor *v)
148a15fcc3cSEric Blake {
149a15fcc3cSEric Blake     g_free(v);
150a15fcc3cSEric Blake }
151a15fcc3cSEric Blake 
qapi_clone_visitor_new(void)152b0409139SAkihiko Odaki Visitor *qapi_clone_visitor_new(void)
153a15fcc3cSEric Blake {
154a15fcc3cSEric Blake     QapiCloneVisitor *v;
155a15fcc3cSEric Blake 
156a15fcc3cSEric Blake     v = g_malloc0(sizeof(*v));
157a15fcc3cSEric Blake 
158a15fcc3cSEric Blake     v->visitor.type = VISITOR_CLONE;
159a15fcc3cSEric Blake     v->visitor.start_struct = qapi_clone_start_struct;
160a15fcc3cSEric Blake     v->visitor.end_struct = qapi_clone_end;
161a15fcc3cSEric Blake     v->visitor.start_list = qapi_clone_start_list;
162a15fcc3cSEric Blake     v->visitor.next_list = qapi_clone_next_list;
163a15fcc3cSEric Blake     v->visitor.end_list = qapi_clone_end;
164a15fcc3cSEric Blake     v->visitor.start_alternate = qapi_clone_start_alternate;
165a15fcc3cSEric Blake     v->visitor.end_alternate = qapi_clone_end;
166a15fcc3cSEric Blake     v->visitor.type_int64 = qapi_clone_type_int64;
167a15fcc3cSEric Blake     v->visitor.type_uint64 = qapi_clone_type_uint64;
168a15fcc3cSEric Blake     v->visitor.type_bool = qapi_clone_type_bool;
169a15fcc3cSEric Blake     v->visitor.type_str = qapi_clone_type_str;
170a15fcc3cSEric Blake     v->visitor.type_number = qapi_clone_type_number;
171a15fcc3cSEric Blake     v->visitor.type_null = qapi_clone_type_null;
172a15fcc3cSEric Blake     v->visitor.free = qapi_clone_free;
173a15fcc3cSEric Blake 
174a15fcc3cSEric Blake     return &v->visitor;
175a15fcc3cSEric Blake }
176a15fcc3cSEric Blake 
qapi_clone_members_visitor_new(void)177b0409139SAkihiko Odaki Visitor *qapi_clone_members_visitor_new(void)
178a15fcc3cSEric Blake {
179b0409139SAkihiko Odaki     Visitor *v = qapi_clone_visitor_new();
1804626a19cSMarkus Armbruster     to_qcv(v)->depth++;
181b0409139SAkihiko Odaki     return v;
1824626a19cSMarkus Armbruster }
183