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