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