qemu/qobject/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 "qapi/qmp/qlist.h"
  14#include "qapi/qmp/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 = g_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 = g_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    g_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
 127static void qlist_size_iter(QObject *obj, void *opaque)
 128{
 129    size_t *count = opaque;
 130    (*count)++;
 131}
 132
 133size_t qlist_size(const QList *qlist)
 134{
 135    size_t count = 0;
 136    qlist_iter(qlist, qlist_size_iter, &count);
 137    return count;
 138}
 139
 140/**
 141 * qobject_to_qlist(): Convert a QObject into a QList
 142 */
 143QList *qobject_to_qlist(const QObject *obj)
 144{
 145    if (qobject_type(obj) != QTYPE_QLIST) {
 146        return NULL;
 147    }
 148
 149    return container_of(obj, QList, base);
 150}
 151
 152/**
 153 * qlist_destroy_obj(): Free all the memory allocated by a QList
 154 */
 155static void qlist_destroy_obj(QObject *obj)
 156{
 157    QList *qlist;
 158    QListEntry *entry, *next_entry;
 159
 160    assert(obj != NULL);
 161    qlist = qobject_to_qlist(obj);
 162
 163    QTAILQ_FOREACH_SAFE(entry, &qlist->head, next, next_entry) {
 164        QTAILQ_REMOVE(&qlist->head, entry, next);
 165        qobject_decref(entry->value);
 166        g_free(entry);
 167    }
 168
 169    g_free(qlist);
 170}
 171