common: Simple list implementation.

This commit is contained in:
Juho Hämäläinen 2022-02-23 10:33:03 +02:00
parent b4fb20eafe
commit eefdb31f57
3 changed files with 221 additions and 2 deletions

View file

@ -18,7 +18,8 @@ includedir = @includedir@/pulsecore/modules/droid
include_HEADERS = include/droid/version.h \
include/droid/conversion.h \
include/droid/droid-config.h \
include/droid/droid-util.h
include/droid/droid-util.h \
include/droid/sllist.h
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libdroid-util.pc
@ -27,6 +28,7 @@ libdroid_util_la_SOURCES = droid-util.c \
droid-config.c \
conversion.c \
config-parser-xml.c \
sllist.c \
droid-util-audio.h
libdroid_util_la_LDFLAGS = -avoid-version -Wl,-z,noexecstack -lhybris-common $(SBJ_DEVICE_LDFLAGS)
libdroid_util_la_LIBADD = $(AM_LIBADD)

View file

@ -2,7 +2,7 @@
#define foosllistfoo
/*
* Copyright (C) 2018 Jolla Ltd.
* Copyright (C) 2018-2022 Jolla Ltd.
*
* Contact: Juho Hämäläinen <juho.hamalainen@jolla.com>
*
@ -22,6 +22,12 @@
* USA.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdbool.h>
#include <pulse/def.h>
#define SLLIST_APPEND(t, head, item) \
do { \
item->next = NULL; \
@ -46,4 +52,43 @@
i = NULL; \
} while (0)
typedef struct dm_list_entry dm_list_entry;
typedef struct dm_list dm_list;
struct dm_list_entry {
struct dm_list_entry *next;
struct dm_list_entry *prev;
void *data;
};
struct dm_list {
struct dm_list_entry *head;
struct dm_list_entry *tail;
ssize_t size;
};
dm_list *dm_list_new(void);
void dm_list_free(dm_list *list, pa_free_cb_t free_cb);
bool dm_list_remove(dm_list *list, dm_list_entry *entry);
void dm_list_prepend(dm_list *list, void *data);
void dm_list_push_back(dm_list *list, void *data);
dm_list_entry *dm_list_last(dm_list *list);
void *dm_list_steal_first(dm_list *list);
ssize_t dm_list_size(dm_list *list);
void *dm_list_first_data(dm_list *list, void **state);
void *dm_list_next_data(dm_list *list, void **state);
/* For example
* dm_list *list;
* void *state;
* my_data *data;
* DM_LIST_FOREACH_DATA(data, list, state) {
* do_something_with_my(data);
* }
*/
#define DM_LIST_FOREACH_DATA(i, list, state) \
for (i = dm_list_first_data(list, &(state)); state; i = dm_list_next_data(list, &(state)))
/* Access i->data */
#define DM_LIST_FOREACH(i, list) \
for (i = list->head; i; i = i->next)
#endif

172
src/common/sllist.c Normal file
View file

@ -0,0 +1,172 @@
/*
* Copyright (C) 2022 Jolla Ltd.
*
* Contact: Juho Hämäläinen <juho.hamalainen@jolla.com>
*
* These PulseAudio Modules are free software; you can redistribute
* it and/or modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation
* version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
* USA.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <pulse/xmalloc.h>
#include <pulsecore/macro.h>
#include "droid/sllist.h"
dm_list *dm_list_new(void) {
return pa_xnew0(dm_list, 1);
}
void dm_list_free(dm_list *list, pa_free_cb_t free_cb) {
pa_assert(list);
while (list->head) {
void *data = dm_list_steal_first(list);
if (free_cb)
free_cb(data);
}
pa_xfree(list);
}
bool dm_list_remove(dm_list *list, dm_list_entry *entry) {
dm_list_entry *i;
bool removed = false;
for (i = list->head; i; i = i->next) {
if (i == entry) {
removed = true;
if (list->head == entry)
list->head = entry->next;
if (list->tail == entry)
list->tail = entry->prev;
if (entry->next)
entry->next->prev = entry->prev;
if (entry->prev)
entry->prev->next = entry->next;
pa_xfree(entry);
break;
}
}
return removed;
}
void dm_list_prepend(dm_list *list, void *data) {
dm_list_entry *entry;
pa_assert(list);
entry = pa_xnew0(dm_list_entry, 1);
entry->data = data;
if (!list->tail)
list->tail = entry;
if (list->head) {
entry->next = list->head;
list->head->prev = entry;
}
list->head = entry;
list->size++;
}
void dm_list_push_back(dm_list *list, void *data) {
dm_list_entry *entry;
pa_assert(list);
entry = pa_xnew0(dm_list_entry, 1);
entry->data = data;
if (!list->head)
list->head = entry;
if (list->tail) {
list->tail->next = entry;
entry->prev = list->tail;
}
list->tail = entry;
list->size++;
}
dm_list_entry *dm_list_last(dm_list *list) {
pa_assert(list);
return list->tail;
}
void *dm_list_steal_first(dm_list *list) {
dm_list_entry *entry;
void *data = NULL;
pa_assert(list);
if (list->head) {
data = list->head->data;
entry = list->head;
if (list->head == list->tail) {
list->head = NULL;
list->tail = NULL;
} else {
list->head->next->prev = NULL;
list->head = list->head->next;
}
pa_xfree(entry);
list->size--;
}
return data;
}
ssize_t dm_list_size(dm_list *list) {
pa_assert(list);
return list->size;
}
/* For iteration */
void *dm_list_first_data(dm_list *list, void **state) {
pa_assert(list);
pa_assert(state);
*state = list->head;
if (list->head)
return list->head->data;
else
return NULL;
}
void *dm_list_next_data(dm_list *list, void **state) {
dm_list_entry *entry;
pa_assert(list);
pa_assert(state);
entry = *state;
*state = entry->next;
if (entry->next)
return entry->next->data;
else
return NULL;
}