From 534aaf07ab697bbad4f48c805ebfa4ebb380891c Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 27 Dec 2013 19:31:14 -0800 Subject: [PATCH] shared: Add simple queue handling functions --- src/shared/queue.c | 261 +++++++++++++++++++++++++++++++++++++++++++++ src/shared/queue.h | 51 +++++++++ 2 files changed, 312 insertions(+) create mode 100644 src/shared/queue.c create mode 100644 src/shared/queue.h diff --git a/src/shared/queue.c b/src/shared/queue.c new file mode 100644 index 000000000..27a030b93 --- /dev/null +++ b/src/shared/queue.c @@ -0,0 +1,261 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2012 Intel Corporation. All rights reserved. + * + * + * This library is 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; either + * version 2.1 of the License, or (at your option) any later version. + * + * 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 St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "util.h" +#include "queue.h" + +struct queue_entry { + void *data; + struct queue_entry *next; +}; + +struct queue { + struct queue_entry *head; + struct queue_entry *tail; + unsigned int entries; +}; + +struct queue *queue_new(void) +{ + struct queue *queue; + + queue = new0(struct queue, 1); + if (!queue) + return NULL; + + queue->head = NULL; + queue->tail = NULL; + queue->entries = 0; + + return queue; +} + +void queue_destroy(struct queue *queue, queue_destroy_func_t destroy) +{ + struct queue_entry *entry; + + if (!queue) + return; + + entry = queue->head; + + while (entry) { + struct queue_entry *tmp = entry; + + if (destroy) + destroy(entry->data); + + entry = entry->next; + + free(tmp); + } + + free(queue); +} + +bool queue_push_tail(struct queue *queue, void *data) +{ + struct queue_entry *entry; + + if (!queue) + return false; + + entry = new0(struct queue_entry, 1); + if (!entry) + return false; + + entry->data = data; + entry->next = NULL; + + if (queue->tail) + queue->tail->next = entry; + + queue->tail = entry; + + if (!queue->head) + queue->head = entry; + + queue->entries++; + + return true; +} + +bool queue_push_head(struct queue *queue, void *data) +{ + struct queue_entry *entry; + + if (!queue) + return false; + + entry = new0(struct queue_entry, 1); + if (!entry) + return false; + + entry->data = data; + entry->next = queue->head; + + queue->head = entry; + + if (!queue->tail) + queue->tail = entry; + + queue->entries++; + + return true; +} + +void *queue_pop_head(struct queue *queue) +{ + struct queue_entry *entry; + void *data; + + if (!queue || !queue->head) + return NULL; + + entry = queue->head; + + if (!queue->head->next) { + queue->head = NULL; + queue->tail = NULL; + } else + queue->head = queue->head->next; + + data = entry->data; + + free(entry); + queue->entries--; + + return data; +} + +void *queue_peek_head(struct queue *queue) +{ + if (!queue || !queue->head) + return NULL; + + return queue->head->data; +} + +void *queue_peek_tail(struct queue *queue) +{ + if (!queue || !queue->tail) + return NULL; + + return queue->tail->data; +} + +void queue_foreach(struct queue *queue, queue_foreach_func_t function, + void *user_data) +{ + struct queue_entry *entry; + + if (!queue || !function) + return; + + for (entry = queue->head; entry; entry = entry->next) + function(entry->data, user_data); +} + +void *queue_remove_if(struct queue *queue, queue_match_func_t function, + void *user_data) +{ + struct queue_entry *entry, *prev = NULL; + + if (!queue || !function) + return NULL; + + entry = queue->head; + + while (entry) { + if (function(entry->data, user_data)) { + void *data; + + if (prev) + prev->next = entry->next; + else + queue->head = entry->next; + + if (!entry->next) + queue->tail = prev; + + data = entry->data; + + free(entry); + queue->entries--; + + return data; + } else { + prev = entry; + entry = entry->next; + } + } + + return NULL; +} + +bool queue_remove_all(struct queue *queue, queue_destroy_func_t destroy) +{ + struct queue_entry *entry; + + if (!queue) + return false; + + entry = queue->head; + + while (entry) { + struct queue_entry *tmp = entry; + + entry = entry->next; + + if (destroy) + destroy(tmp->data); + + free(tmp); + } + + queue->head = NULL; + queue->tail = NULL; + queue->entries = 0; + + return true; +} + +unsigned int queue_length(struct queue *queue) +{ + if (!queue) + return 0; + + return queue->entries; +} + +bool queue_isempty(struct queue *queue) +{ + if (!queue) + return true; + + return queue->entries == 0; +} diff --git a/src/shared/queue.h b/src/shared/queue.h new file mode 100644 index 000000000..66b7564ed --- /dev/null +++ b/src/shared/queue.h @@ -0,0 +1,51 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2012 Intel Corporation. All rights reserved. + * + * + * This library is 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; either + * version 2.1 of the License, or (at your option) any later version. + * + * 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 St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include + +typedef void (*queue_destroy_func_t)(void *data); + +struct queue; + +struct queue *queue_new(void); +void queue_destroy(struct queue *queue, queue_destroy_func_t destroy); + +bool queue_push_tail(struct queue *queue, void *data); +bool queue_push_head(struct queue *queue, void *data); +void *queue_pop_head(struct queue *queue); +void *queue_peek_head(struct queue *queue); +void *queue_peek_tail(struct queue *queue); + +typedef void (*queue_foreach_func_t)(void *data, void *user_data); + +void queue_foreach(struct queue *queue, queue_foreach_func_t function, + void *user_data); + +typedef bool (*queue_match_func_t)(const void *a, const void *b); + +void *queue_remove_if(struct queue *queue, queue_match_func_t function, + void *user_data); +bool queue_remove_all(struct queue *queue, queue_destroy_func_t destroy); + +unsigned int queue_length(struct queue *queue); +bool queue_isempty(struct queue *queue); -- 2.47.3