| /* |
| * |
| * BlueZ - Bluetooth protocol stack for Linux |
| * |
| * Copyright (C) 2004-2006 Marcel Holtmann <marcel@holtmann.org> |
| * Copyright (C) 2005-2006 Johan Hedberg <johan.hedberg@nokia.com> |
| * |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation; either version 2 of the License, or |
| * (at your option) any later version. |
| * |
| * This program 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 General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
| * |
| */ |
| |
| #ifdef HAVE_CONFIG_H |
| #include <config.h> |
| #endif |
| |
| #include <stdio.h> |
| #include <errno.h> |
| #include <malloc.h> |
| |
| #include "list.h" |
| |
| struct slist *slist_append(struct slist *list, void *data) |
| { |
| struct slist *entry, *tail; |
| |
| entry = malloc(sizeof(struct slist)); |
| /* FIXME: this currently just silently fails */ |
| if (!entry) |
| return list; |
| |
| entry->data = data; |
| entry->next = NULL; |
| |
| if (!list) |
| return entry; |
| |
| /* Find the end of the list */ |
| for (tail = list; tail->next; tail = tail->next); |
| |
| tail->next = entry; |
| |
| return list; |
| } |
| |
| struct slist *slist_prepend(struct slist *list, void *data) |
| { |
| struct slist *entry; |
| |
| entry = malloc(sizeof(struct slist)); |
| /* FIXME: this currently just silently fails */ |
| if (!entry) |
| return list; |
| |
| entry->data = data; |
| entry->next = list; |
| |
| return entry; |
| } |
| |
| struct slist *slist_insert_before(struct slist *list, struct slist *sibling, void *data) |
| { |
| struct slist *entry, *prev, *cur; |
| |
| entry = malloc(sizeof(struct slist)); |
| if (!entry) |
| return list; |
| |
| entry->data = data; |
| entry->next = NULL; |
| |
| if (!list) |
| return entry; |
| |
| for (cur = list, prev = NULL; cur != NULL; prev = cur, cur = prev->next) { |
| if (cur == sibling) |
| break; |
| } |
| |
| if (!prev) { |
| entry->next = list; |
| return entry; |
| } |
| |
| entry->next = prev->next; |
| prev->next = entry; |
| |
| return list; |
| } |
| |
| struct slist *slist_remove(struct slist *list, void *data) |
| { |
| struct slist *l, *next, *prev = NULL, *match = NULL; |
| |
| if (!list) |
| return NULL; |
| |
| for (l = list; l != NULL; l = l->next) { |
| if (l->data == data) { |
| match = l; |
| break; |
| } |
| prev = l; |
| } |
| |
| if (!match) |
| return list; |
| |
| next = match->next; |
| |
| free(match); |
| |
| /* If the head was removed, return the next element */ |
| if (!prev) |
| return next; |
| |
| prev->next = next; |
| |
| return list; |
| } |
| |
| struct slist *slist_find(struct slist *list, const void *data, |
| cmp_func_t cmp_func) |
| { |
| struct slist *l; |
| |
| for (l = list; l != NULL; l = l->next) { |
| if (!cmp_func(l->data, data)) |
| return l; |
| } |
| |
| return NULL; |
| } |
| |
| int slist_length(struct slist *list) |
| { |
| int len; |
| |
| for (len = 0; list != NULL; list = list->next) |
| len++; |
| |
| return len; |
| } |
| |
| void slist_foreach(struct slist *list, slist_func_t func, void *user_data) |
| { |
| while (list) { |
| struct slist *next = list->next; |
| func(list->data, user_data); |
| list = next; |
| } |
| } |
| |
| void slist_free(struct slist *list) |
| { |
| struct slist *l, *next; |
| |
| for (l = list; l != NULL; l = next) { |
| next = l->next; |
| free(l); |
| } |
| } |