From 0164da6f9e922787826894d8377ef846b32ebafb Mon Sep 17 00:00:00 2001 From: WaLyong Cho Date: Wed, 14 Dec 2016 15:17:57 +0900 Subject: [PATCH] libsystem: glib-utils: extend glist iterate macro function Some of additional glist iterate macro functions are added: - FOREACH_G_LIST_DATA() - FOREACH_G_LIST_REVERSE() - FOREACH_G_LIST_SAFE() - FOREACH_G_LIST_SAFE_REVERSE() Change-Id: Ie37b40aded588a4c8e725f86b2185c12c3a2e868 Signed-off-by: WaLyong Cho --- src/Makefile.am | 13 ++++ src/libsystem/glib-util.h | 45 +++++++++-- src/test/test-foreach-glist.c | 138 ++++++++++++++++++++++++++++++++++ 3 files changed, 190 insertions(+), 6 deletions(-) create mode 100644 src/test/test-foreach-glist.c diff --git a/src/Makefile.am b/src/Makefile.am index f6cbb81..0b63ea5 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -121,6 +121,19 @@ test_read_write_LDADD = \ tests += test-read-write +# ------------------------------------------------------------------------------ +test_foreach_glist_SOURCES = \ + test/test-foreach-glist.c + +test_foreach_glist_CFLAGS = \ + $(GIO_CFLAGS) + +test_foreach_glist_LDADD = \ + $(GIO_LIBS) \ + libsystem.la + +tests += test-foreach-glist + # ------------------------------------------------------------------------------ pkgconfiglib_DATA += \ libsystem-sd/libsystem-sd.pc diff --git a/src/libsystem/glib-util.h b/src/libsystem/glib-util.h index 7d3c7ad..560acc4 100644 --- a/src/libsystem/glib-util.h +++ b/src/libsystem/glib-util.h @@ -30,9 +30,6 @@ #pragma once #include -#include - -#include "libsystem.h" #ifdef __cplusplus extern "C" { @@ -41,11 +38,47 @@ extern "C" { /** * @brief Iterate for each list nodes. * - * @param n each list nodes + * @param c current node + * @param l list to iterate + */ +#define FOREACH_G_LIST(c, l) \ + for (c = g_list_first(l); c; c = g_list_next(c)) + +/** + * @brief Reverse iterate for each list nodes. + * + * @param c current node + * @param l list to iterate + */ +#define FOREACH_G_LIST_REVERSE(c, l) \ + for (c = g_list_last(l); c; c = g_list_previous(c)) + +/** + * @brief Iterate for each list nodes. #FOREACH_G_LIST_SAFE is similar + * with #FOREACH_G_LIST but safe for list remove. When you are + * iterating a list to remove some of list nodes, you have to use + * #FOREACH_G_LIST_SAFE for safe iteration. + * + * @param c current node + * @param n next node of current iteration, this is used for safe iteration + * @param l list to iterate + */ +#define FOREACH_G_LIST_SAFE(c, n, l) \ + for (c = g_list_first(l), n = g_list_next(c); c; c = n, n = g_list_next(c)) + +/** + * @brief Reverse iterate for each list + * nodes. #FOREACH_G_LIST_SAFE_REVERSE is similar with + * #FOREACH_G_LIST_REVERSE but safe for list remove. When you are + * iterating a list to remove some of list nodes, you have to use + * #FOREACH_G_LIST_SAFE_REVERSE for safe iteration. + * + * @param c current node + * @param p previous node of current iteration, this is used for safe iteration * @param l list to iterate */ -#define FOREACH_G_LIST(n, l) \ - for (n = g_list_first(l); n; n = g_list_next(n)) +#define FOREACH_G_LIST_SAFE_REVERSE(c, p, l) \ + for (c = g_list_last(l), p = g_list_previous(c); c; c = p, p = g_list_previous(c)) /** * @brief Convert GError to errno. diff --git a/src/test/test-foreach-glist.c b/src/test/test-foreach-glist.c new file mode 100644 index 0000000..ba952e0 --- /dev/null +++ b/src/test/test-foreach-glist.c @@ -0,0 +1,138 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/* + * libsystem + * + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include + +#include "libsystem/libsystem.h" +#include "libsystem/glib-util.h" + +static void gen_test_list(GList **list) { + GList *l = NULL; + int i; + + assert(list); + assert(!*list); + + for (i = 1; i <= 10; i++) + l = g_list_append(l, GINT_TO_POINTER(i)); + + *list = l; +} + +static void test_foreach_g_list(void) { + GList *list = NULL, *node; + char buf[LINE_MAX]; + int n = 0; + + gen_test_list(&list); + + FOREACH_G_LIST(node, list) { + int i = GPOINTER_TO_INT(node->data); + + n += snprintf(buf + n, LINE_MAX - n - 1, "%d ", i); + } + + assert(streq(buf, "1 2 3 4 5 6 7 8 9 10 ")); + + g_list_free(list); +} + +static void test_foreach_g_list_reverse(void) { + GList *list = NULL, *node; + char buf[LINE_MAX]; + int n = 0; + + gen_test_list(&list); + + FOREACH_G_LIST_REVERSE(node, list) { + int i = GPOINTER_TO_INT(node->data); + + n += snprintf(buf + n, LINE_MAX - n - 1, "%d ", i); + } + + assert(streq(buf, "10 9 8 7 6 5 4 3 2 1 ")); + + g_list_free(list); +} + +static void test_foreach_g_list_safe(void) { + GList *list = NULL, *node, *next; + char buf[LINE_MAX]; + int n = 0; + + gen_test_list(&list); + + FOREACH_G_LIST_SAFE(node, next, list) { + int i = GPOINTER_TO_INT(node->data); + + if (i % 2) + list = g_list_remove_link(list, node); + } + + FOREACH_G_LIST(node, list) { + int i = GPOINTER_TO_INT(node->data); + + n += snprintf(buf + n, LINE_MAX - n - 1, "%d ", i); + } + + assert(streq(buf, "2 4 6 8 10 ")); + + g_list_free(list); +} + +static void test_foreach_g_list_safe_reverse(void) { + GList *list = NULL, *node, *prev; + char buf[LINE_MAX]; + int n = 0; + + gen_test_list(&list); + + FOREACH_G_LIST_SAFE_REVERSE(node, prev, list) { + int i = GPOINTER_TO_INT(node->data); + + if (i % 2) + list = g_list_remove_link(list, node); + } + + FOREACH_G_LIST_REVERSE(node, list) { + int i = GPOINTER_TO_INT(node->data); + + n += snprintf(buf + n, LINE_MAX - n - 1, "%d ", i); + } + + assert(streq(buf, "10 8 6 4 2 ")); + + g_list_free(list); +} + +int main(int argc, char *argv[]) { + + test_foreach_g_list(); + test_foreach_g_list_reverse(); + + test_foreach_g_list_safe(); + test_foreach_g_list_safe_reverse(); + + return 0; +} -- 2.34.1