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 "qapi/qmp/qlist.h" 14 #include "qapi/qmp/qobject.h" 15 #include "qemu/queue.h" 16 #include "qemu-common.h" 17 18 /** 19 * qlist_new(): Create a new QList 20 * 21 * Return strong reference. 22 */ 23 QList *qlist_new(void) 24 { 25 QList *qlist; 26 27 qlist = g_malloc(sizeof(*qlist)); 28 qobject_init(QOBJECT(qlist), QTYPE_QLIST); 29 QTAILQ_INIT(&qlist->head); 30 31 return qlist; 32 } 33 34 static void qlist_copy_elem(QObject *obj, void *opaque) 35 { 36 QList *dst = opaque; 37 38 qobject_incref(obj); 39 qlist_append_obj(dst, obj); 40 } 41 42 QList *qlist_copy(QList *src) 43 { 44 QList *dst = qlist_new(); 45 46 qlist_iter(src, qlist_copy_elem, dst); 47 48 return dst; 49 } 50 51 /** 52 * qlist_append_obj(): Append an QObject into QList 53 * 54 * NOTE: ownership of 'value' is transferred to the QList 55 */ 56 void qlist_append_obj(QList *qlist, QObject *value) 57 { 58 QListEntry *entry; 59 60 entry = g_malloc(sizeof(*entry)); 61 entry->value = value; 62 63 QTAILQ_INSERT_TAIL(&qlist->head, entry, next); 64 } 65 66 /** 67 * qlist_iter(): Iterate over all the list's stored values. 68 * 69 * This function allows the user to provide an iterator, which will be 70 * called for each stored value in the list. 71 */ 72 void qlist_iter(const QList *qlist, 73 void (*iter)(QObject *obj, void *opaque), void *opaque) 74 { 75 QListEntry *entry; 76 77 QTAILQ_FOREACH(entry, &qlist->head, next) 78 iter(entry->value, opaque); 79 } 80 81 QObject *qlist_pop(QList *qlist) 82 { 83 QListEntry *entry; 84 QObject *ret; 85 86 if (qlist == NULL || QTAILQ_EMPTY(&qlist->head)) { 87 return NULL; 88 } 89 90 entry = QTAILQ_FIRST(&qlist->head); 91 QTAILQ_REMOVE(&qlist->head, entry, next); 92 93 ret = entry->value; 94 g_free(entry); 95 96 return ret; 97 } 98 99 QObject *qlist_peek(QList *qlist) 100 { 101 QListEntry *entry; 102 QObject *ret; 103 104 if (qlist == NULL || QTAILQ_EMPTY(&qlist->head)) { 105 return NULL; 106 } 107 108 entry = QTAILQ_FIRST(&qlist->head); 109 110 ret = entry->value; 111 112 return ret; 113 } 114 115 int qlist_empty(const QList *qlist) 116 { 117 return QTAILQ_EMPTY(&qlist->head); 118 } 119 120 static void qlist_size_iter(QObject *obj, void *opaque) 121 { 122 size_t *count = opaque; 123 (*count)++; 124 } 125 126 size_t qlist_size(const QList *qlist) 127 { 128 size_t count = 0; 129 qlist_iter(qlist, qlist_size_iter, &count); 130 return count; 131 } 132 133 /** 134 * qobject_to_qlist(): Convert a QObject into a QList 135 */ 136 QList *qobject_to_qlist(const QObject *obj) 137 { 138 if (!obj || qobject_type(obj) != QTYPE_QLIST) { 139 return NULL; 140 } 141 return container_of(obj, QList, base); 142 } 143 144 /** 145 * qlist_destroy_obj(): Free all the memory allocated by a QList 146 */ 147 void qlist_destroy_obj(QObject *obj) 148 { 149 QList *qlist; 150 QListEntry *entry, *next_entry; 151 152 assert(obj != NULL); 153 qlist = qobject_to_qlist(obj); 154 155 QTAILQ_FOREACH_SAFE(entry, &qlist->head, next, next_entry) { 156 QTAILQ_REMOVE(&qlist->head, entry, next); 157 qobject_decref(entry->value); 158 g_free(entry); 159 } 160 161 g_free(qlist); 162 } 163