1 /* 2 * QList Module 3 * 4 * Copyright (C) 2009 Red Hat Inc. 5 * 6 * Authors: 7 * Luiz Capitulino <lcapitulino@redhat.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 #include "qemu/osdep.h" 14 #include "qapi/qmp/qbool.h" 15 #include "qapi/qmp/qlist.h" 16 #include "qapi/qmp/qnull.h" 17 #include "qapi/qmp/qnum.h" 18 #include "qapi/qmp/qstring.h" 19 #include "qemu/queue.h" 20 #include "qemu-common.h" 21 22 /** 23 * qlist_new(): Create a new QList 24 * 25 * Return strong reference. 26 */ 27 QList *qlist_new(void) 28 { 29 QList *qlist; 30 31 qlist = g_malloc(sizeof(*qlist)); 32 qobject_init(QOBJECT(qlist), QTYPE_QLIST); 33 QTAILQ_INIT(&qlist->head); 34 35 return qlist; 36 } 37 38 static void qlist_copy_elem(QObject *obj, void *opaque) 39 { 40 QList *dst = opaque; 41 42 qobject_ref(obj); 43 qlist_append_obj(dst, obj); 44 } 45 46 QList *qlist_copy(QList *src) 47 { 48 QList *dst = qlist_new(); 49 50 qlist_iter(src, qlist_copy_elem, dst); 51 52 return dst; 53 } 54 55 /** 56 * qlist_append_obj(): Append an QObject into QList 57 * 58 * NOTE: ownership of 'value' is transferred to the QList 59 */ 60 void qlist_append_obj(QList *qlist, QObject *value) 61 { 62 QListEntry *entry; 63 64 entry = g_malloc(sizeof(*entry)); 65 entry->value = value; 66 67 QTAILQ_INSERT_TAIL(&qlist->head, entry, next); 68 } 69 70 void qlist_append_int(QList *qlist, int64_t value) 71 { 72 qlist_append(qlist, qnum_from_int(value)); 73 } 74 75 void qlist_append_bool(QList *qlist, bool value) 76 { 77 qlist_append(qlist, qbool_from_bool(value)); 78 } 79 80 void qlist_append_str(QList *qlist, const char *value) 81 { 82 qlist_append(qlist, qstring_from_str(value)); 83 } 84 85 void qlist_append_null(QList *qlist) 86 { 87 qlist_append(qlist, qnull()); 88 } 89 90 /** 91 * qlist_iter(): Iterate over all the list's stored values. 92 * 93 * This function allows the user to provide an iterator, which will be 94 * called for each stored value in the list. 95 */ 96 void qlist_iter(const QList *qlist, 97 void (*iter)(QObject *obj, void *opaque), void *opaque) 98 { 99 QListEntry *entry; 100 101 QTAILQ_FOREACH(entry, &qlist->head, next) 102 iter(entry->value, opaque); 103 } 104 105 QObject *qlist_pop(QList *qlist) 106 { 107 QListEntry *entry; 108 QObject *ret; 109 110 if (qlist == NULL || QTAILQ_EMPTY(&qlist->head)) { 111 return NULL; 112 } 113 114 entry = QTAILQ_FIRST(&qlist->head); 115 QTAILQ_REMOVE(&qlist->head, entry, next); 116 117 ret = entry->value; 118 g_free(entry); 119 120 return ret; 121 } 122 123 QObject *qlist_peek(QList *qlist) 124 { 125 QListEntry *entry; 126 127 if (qlist == NULL || QTAILQ_EMPTY(&qlist->head)) { 128 return NULL; 129 } 130 131 entry = QTAILQ_FIRST(&qlist->head); 132 133 return entry->value; 134 } 135 136 int qlist_empty(const QList *qlist) 137 { 138 return QTAILQ_EMPTY(&qlist->head); 139 } 140 141 static void qlist_size_iter(QObject *obj, void *opaque) 142 { 143 size_t *count = opaque; 144 (*count)++; 145 } 146 147 size_t qlist_size(const QList *qlist) 148 { 149 size_t count = 0; 150 qlist_iter(qlist, qlist_size_iter, &count); 151 return count; 152 } 153 154 /** 155 * qlist_is_equal(): Test whether the two QLists are equal 156 * 157 * In order to be considered equal, the respective two objects at each 158 * index of the two lists have to compare equal (regarding 159 * qobject_is_equal()), and both lists have to have the same number of 160 * elements. 161 * That means both lists have to contain equal objects in equal order. 162 */ 163 bool qlist_is_equal(const QObject *x, const QObject *y) 164 { 165 const QList *list_x = qobject_to(QList, x); 166 const QList *list_y = qobject_to(QList, y); 167 const QListEntry *entry_x, *entry_y; 168 169 entry_x = qlist_first(list_x); 170 entry_y = qlist_first(list_y); 171 172 while (entry_x && entry_y) { 173 if (!qobject_is_equal(qlist_entry_obj(entry_x), 174 qlist_entry_obj(entry_y))) 175 { 176 return false; 177 } 178 179 entry_x = qlist_next(entry_x); 180 entry_y = qlist_next(entry_y); 181 } 182 183 return !entry_x && !entry_y; 184 } 185 186 /** 187 * qlist_destroy_obj(): Free all the memory allocated by a QList 188 */ 189 void qlist_destroy_obj(QObject *obj) 190 { 191 QList *qlist; 192 QListEntry *entry, *next_entry; 193 194 assert(obj != NULL); 195 qlist = qobject_to(QList, obj); 196 197 QTAILQ_FOREACH_SAFE(entry, &qlist->head, next, next_entry) { 198 QTAILQ_REMOVE(&qlist->head, entry, next); 199 qobject_unref(entry->value); 200 g_free(entry); 201 } 202 203 g_free(qlist); 204 } 205