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