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