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