1 /* 2 * Dealloc Visitor 3 * 4 * Copyright IBM, Corp. 2011 5 * 6 * Authors: 7 * Michael Roth <mdroth@linux.vnet.ibm.com> 8 * 9 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. 10 * See the COPYING.LIB file in the top-level directory. 11 * 12 */ 13 14 #include "qapi-dealloc-visitor.h" 15 #include "qemu-queue.h" 16 #include "qemu-common.h" 17 #include "qemu-objects.h" 18 19 typedef struct StackEntry 20 { 21 void *value; 22 bool is_list_head; 23 QTAILQ_ENTRY(StackEntry) node; 24 } StackEntry; 25 26 struct QapiDeallocVisitor 27 { 28 Visitor visitor; 29 QTAILQ_HEAD(, StackEntry) stack; 30 bool is_list_head; 31 }; 32 33 static QapiDeallocVisitor *to_qov(Visitor *v) 34 { 35 return container_of(v, QapiDeallocVisitor, visitor); 36 } 37 38 static void qapi_dealloc_push(QapiDeallocVisitor *qov, void *value) 39 { 40 StackEntry *e = g_malloc0(sizeof(*e)); 41 42 e->value = value; 43 44 /* see if we're just pushing a list head tracker */ 45 if (value == NULL) { 46 e->is_list_head = true; 47 } 48 QTAILQ_INSERT_HEAD(&qov->stack, e, node); 49 } 50 51 static void *qapi_dealloc_pop(QapiDeallocVisitor *qov) 52 { 53 StackEntry *e = QTAILQ_FIRST(&qov->stack); 54 QObject *value; 55 QTAILQ_REMOVE(&qov->stack, e, node); 56 value = e->value; 57 g_free(e); 58 return value; 59 } 60 61 static void qapi_dealloc_start_struct(Visitor *v, void **obj, const char *kind, 62 const char *name, size_t unused, 63 Error **errp) 64 { 65 QapiDeallocVisitor *qov = to_qov(v); 66 qapi_dealloc_push(qov, obj); 67 } 68 69 static void qapi_dealloc_end_struct(Visitor *v, Error **errp) 70 { 71 QapiDeallocVisitor *qov = to_qov(v); 72 void **obj = qapi_dealloc_pop(qov); 73 if (obj) { 74 g_free(*obj); 75 } 76 } 77 78 static void qapi_dealloc_start_list(Visitor *v, const char *name, Error **errp) 79 { 80 QapiDeallocVisitor *qov = to_qov(v); 81 qapi_dealloc_push(qov, NULL); 82 } 83 84 static GenericList *qapi_dealloc_next_list(Visitor *v, GenericList **listp, 85 Error **errp) 86 { 87 GenericList *list = *listp; 88 QapiDeallocVisitor *qov = to_qov(v); 89 StackEntry *e = QTAILQ_FIRST(&qov->stack); 90 91 if (e && e->is_list_head) { 92 e->is_list_head = false; 93 return list; 94 } 95 96 if (list) { 97 list = list->next; 98 g_free(*listp); 99 return list; 100 } 101 102 return NULL; 103 } 104 105 static void qapi_dealloc_end_list(Visitor *v, Error **errp) 106 { 107 QapiDeallocVisitor *qov = to_qov(v); 108 void *obj = qapi_dealloc_pop(qov); 109 assert(obj == NULL); /* should've been list head tracker with no payload */ 110 } 111 112 static void qapi_dealloc_type_str(Visitor *v, char **obj, const char *name, 113 Error **errp) 114 { 115 if (obj) { 116 g_free(*obj); 117 } 118 } 119 120 static void qapi_dealloc_type_int(Visitor *v, int64_t *obj, const char *name, 121 Error **errp) 122 { 123 } 124 125 static void qapi_dealloc_type_bool(Visitor *v, bool *obj, const char *name, 126 Error **errp) 127 { 128 } 129 130 static void qapi_dealloc_type_number(Visitor *v, double *obj, const char *name, 131 Error **errp) 132 { 133 } 134 135 static void qapi_dealloc_type_enum(Visitor *v, int *obj, const char *strings[], 136 const char *kind, const char *name, 137 Error **errp) 138 { 139 } 140 141 Visitor *qapi_dealloc_get_visitor(QapiDeallocVisitor *v) 142 { 143 return &v->visitor; 144 } 145 146 void qapi_dealloc_visitor_cleanup(QapiDeallocVisitor *v) 147 { 148 g_free(v); 149 } 150 151 QapiDeallocVisitor *qapi_dealloc_visitor_new(void) 152 { 153 QapiDeallocVisitor *v; 154 155 v = g_malloc0(sizeof(*v)); 156 157 v->visitor.start_struct = qapi_dealloc_start_struct; 158 v->visitor.end_struct = qapi_dealloc_end_struct; 159 v->visitor.start_list = qapi_dealloc_start_list; 160 v->visitor.next_list = qapi_dealloc_next_list; 161 v->visitor.end_list = qapi_dealloc_end_list; 162 v->visitor.type_enum = qapi_dealloc_type_enum; 163 v->visitor.type_int = qapi_dealloc_type_int; 164 v->visitor.type_bool = qapi_dealloc_type_bool; 165 v->visitor.type_str = qapi_dealloc_type_str; 166 v->visitor.type_number = qapi_dealloc_type_number; 167 168 QTAILQ_INIT(&v->stack); 169 170 return v; 171 } 172