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" 1584be629dSMax Reitz #include "qapi/qmp/qnull.h" 16a15fcc3cSEric Blake 17a15fcc3cSEric Blake struct QapiCloneVisitor { 18a15fcc3cSEric Blake Visitor visitor; 19a15fcc3cSEric Blake size_t depth; 20a15fcc3cSEric Blake }; 21a15fcc3cSEric Blake 22a15fcc3cSEric Blake static QapiCloneVisitor *to_qcv(Visitor *v) 23a15fcc3cSEric Blake { 24a15fcc3cSEric Blake return container_of(v, QapiCloneVisitor, visitor); 25a15fcc3cSEric Blake } 26a15fcc3cSEric Blake 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 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 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 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 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 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 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 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 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 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 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 147a15fcc3cSEric Blake static void qapi_clone_free(Visitor *v) 148a15fcc3cSEric Blake { 149a15fcc3cSEric Blake g_free(v); 150a15fcc3cSEric Blake } 151a15fcc3cSEric Blake 152*b0409139SAkihiko 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 177*b0409139SAkihiko Odaki Visitor *qapi_clone_members_visitor_new(void) 178a15fcc3cSEric Blake { 179*b0409139SAkihiko Odaki Visitor *v = qapi_clone_visitor_new(); 1804626a19cSMarkus Armbruster to_qcv(v)->depth++; 181*b0409139SAkihiko Odaki return v; 1824626a19cSMarkus Armbruster } 183