qapi: dealloc visitor, fix premature free and iteration logic
[sdk/emulator/qemu.git] / qapi / qapi-dealloc-visitor.c
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     QTAILQ_ENTRY(StackEntry) node;
23 } StackEntry;
24
25 struct QapiDeallocVisitor
26 {
27     Visitor visitor;
28     QTAILQ_HEAD(, StackEntry) stack;
29     bool is_list_head;
30 };
31
32 static QapiDeallocVisitor *to_qov(Visitor *v)
33 {
34     return container_of(v, QapiDeallocVisitor, visitor);
35 }
36
37 static void qapi_dealloc_push(QapiDeallocVisitor *qov, void *value)
38 {
39     StackEntry *e = g_malloc0(sizeof(*e));
40
41     e->value = value;
42     QTAILQ_INSERT_HEAD(&qov->stack, e, node);
43 }
44
45 static void *qapi_dealloc_pop(QapiDeallocVisitor *qov)
46 {
47     StackEntry *e = QTAILQ_FIRST(&qov->stack);
48     QObject *value;
49     QTAILQ_REMOVE(&qov->stack, e, node);
50     value = e->value;
51     g_free(e);
52     return value;
53 }
54
55 static void qapi_dealloc_start_struct(Visitor *v, void **obj, const char *kind,
56                                       const char *name, size_t unused,
57                                       Error **errp)
58 {
59     QapiDeallocVisitor *qov = to_qov(v);
60     qapi_dealloc_push(qov, obj);
61 }
62
63 static void qapi_dealloc_end_struct(Visitor *v, Error **errp)
64 {
65     QapiDeallocVisitor *qov = to_qov(v);
66     void **obj = qapi_dealloc_pop(qov);
67     if (obj) {
68         g_free(*obj);
69     }
70 }
71
72 static void qapi_dealloc_start_list(Visitor *v, const char *name, Error **errp)
73 {
74     QapiDeallocVisitor *qov = to_qov(v);
75     qov->is_list_head = true;
76 }
77
78 static GenericList *qapi_dealloc_next_list(Visitor *v, GenericList **listp,
79                                            Error **errp)
80 {
81     GenericList *list = *listp;
82     QapiDeallocVisitor *qov = to_qov(v);
83
84     if (!qov->is_list_head) {
85         *listp = list->next;
86         g_free(list);
87         return *listp;
88     }
89
90     qov->is_list_head = false;
91     return list;
92 }
93
94 static void qapi_dealloc_end_list(Visitor *v, Error **errp)
95 {
96 }
97
98 static void qapi_dealloc_type_str(Visitor *v, char **obj, const char *name,
99                                   Error **errp)
100 {
101     if (obj) {
102         g_free(*obj);
103     }
104 }
105
106 static void qapi_dealloc_type_int(Visitor *v, int64_t *obj, const char *name,
107                                   Error **errp)
108 {
109 }
110
111 static void qapi_dealloc_type_bool(Visitor *v, bool *obj, const char *name,
112                                    Error **errp)
113 {
114 }
115
116 static void qapi_dealloc_type_number(Visitor *v, double *obj, const char *name,
117                                      Error **errp)
118 {
119 }
120
121 static void qapi_dealloc_type_enum(Visitor *v, int *obj, const char *strings[],
122                                    const char *kind, const char *name,
123                                    Error **errp)
124 {
125 }
126
127 Visitor *qapi_dealloc_get_visitor(QapiDeallocVisitor *v)
128 {
129     return &v->visitor;
130 }
131
132 void qapi_dealloc_visitor_cleanup(QapiDeallocVisitor *v)
133 {
134     g_free(v);
135 }
136
137 QapiDeallocVisitor *qapi_dealloc_visitor_new(void)
138 {
139     QapiDeallocVisitor *v;
140
141     v = g_malloc0(sizeof(*v));
142
143     v->visitor.start_struct = qapi_dealloc_start_struct;
144     v->visitor.end_struct = qapi_dealloc_end_struct;
145     v->visitor.start_list = qapi_dealloc_start_list;
146     v->visitor.next_list = qapi_dealloc_next_list;
147     v->visitor.end_list = qapi_dealloc_end_list;
148     v->visitor.type_enum = qapi_dealloc_type_enum;
149     v->visitor.type_int = qapi_dealloc_type_int;
150     v->visitor.type_bool = qapi_dealloc_type_bool;
151     v->visitor.type_str = qapi_dealloc_type_str;
152     v->visitor.type_number = qapi_dealloc_type_number;
153
154     QTAILQ_INIT(&v->stack);
155
156     return v;
157 }