xref: /qemu/qapi/qapi-dealloc-visitor.c (revision a828f1b0)
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