qemu/qlist.c
<<
>>
Prefs
   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 "qlist.h"
  14#include "qobject.h"
  15#include "qemu-queue.h"
  16#include "qemu-common.h"
  17
  18static void qlist_destroy_obj(QObject *obj);
  19
  20static 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 */
  30QList *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
  41static 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
  49QList *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 */
  63void 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 */
  79void 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
  88QObject *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
 106QObject *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
 122int 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 */
 130QList *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 */
 142static 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