diff --git a/.clang-format b/.clang-format index dd5e08d0662..6a23028c113 100644 --- a/.clang-format +++ b/.clang-format @@ -22,7 +22,7 @@ AlignConsecutiveMacros: true AlignTrailingComments: false AlignOperands: false Cpp11BracedListStyle: false -ForEachMacros: ['rz_list_foreach', 'rz_list_foreach_safe', 'rz_vector_foreach', 'rz_vector_foreach_prev', 'rz_vector_enumerate', 'rz_pvector_foreach', 'rz_pvector_enumerate', 'rz_rbtree_foreach', 'rz_interval_tree_foreach', 'rz_skiplist_foreach', 'graph_foreach_anode'] +ForEachMacros: ['rz_list_foreach', 'rz_list_foreach_enum', 'rz_list_foreach_safe', 'rz_vector_foreach', 'rz_vector_foreach_prev', 'rz_vector_enumerate', 'rz_pvector_foreach', 'rz_pvector_enumerate', 'rz_rbtree_foreach', 'rz_interval_tree_foreach', 'rz_skiplist_foreach', 'graph_foreach_anode'] SortIncludes: false RequiresClausePosition: SingleLine -TypenameMacros: ['HT_', 'Ht_', 'HtName_'] \ No newline at end of file +TypenameMacros: ['HT_', 'Ht_', 'HtName_'] diff --git a/librz/include/rz_list.h b/librz/include/rz_list.h index cff7d6d820b..18ccd8e3dc2 100644 --- a/librz/include/rz_list.h +++ b/librz/include/rz_list.h @@ -1,6 +1,7 @@ #ifndef RZ_LIST_H #define RZ_LIST_H +#include #include #ifdef __cplusplus @@ -33,6 +34,9 @@ typedef int (*RzListComparator)(const void *value, const void *list_data, void * #define rz_list_foreach(list, it, pos) \ if (list) \ for (it = list->head; it && (pos = it->elem, 1); it = it->next) +#define rz_list_foreach_enum(list, it, pos, i) \ + if (list) \ + for (it = list->head, i = 0; it && (pos = it->elem, 1); it = it->next, ++i) #define rz_list_foreach_iter(iter, it, pos) \ for (it = iter; it && (pos = it->elem, 1); it = it->next) /* Safe when calling rz_list_delete() while iterating over the list. */ @@ -62,6 +66,7 @@ typedef int (*RzListComparator)(const void *value, const void *list_data, void * RZ_API RZ_OWN RzList *rz_list_new(void); RZ_API RZ_OWN RzList *rz_list_newf(RZ_NULLABLE RzListFree f); RZ_API RZ_OWN RzList *rz_list_new_from_array(RZ_NONNULL const void **arr, size_t arr_size); +RZ_API RZ_OWN RzList *rz_list_new_from_iterator(RZ_BORROW RZ_NONNULL RzIterator *iter); RZ_API RZ_BORROW RzListIter *rz_list_iter_get_prev(RZ_NONNULL RzListIter *iter); RZ_API RZ_BORROW RzListIter *rz_list_iter_get_next(RZ_NONNULL RzListIter *iter); RZ_API RZ_BORROW void *rz_list_iter_get_prev_data(RZ_NONNULL RzListIter *iter); diff --git a/librz/util/list.c b/librz/util/list.c index 1e03892c5de..19846e074a5 100644 --- a/librz/util/list.c +++ b/librz/util/list.c @@ -296,6 +296,24 @@ RZ_API RZ_OWN RzList *rz_list_new_from_array(RZ_NONNULL const void **arr, size_t return l; } +/** + * \brief Allocates a new RzList and adds all elements of the iterator \p iter to it. + * \p iter keeps the ownership over the values. + * + * \return The produced list. Or NULL in case of failure. + **/ +RZ_API RZ_OWN RzList *rz_list_new_from_iterator(RZ_BORROW RZ_NONNULL RzIterator *iter) { + RzList *l = rz_list_new(); + if (!l) { + return NULL; + } + void **val; + rz_iterator_foreach(iter, val) { + rz_list_append(l, (void *)*val); + } + return l; +} + /** * \brief Creates a RzListIter element that can be inserted into a RzList * diff --git a/test/unit/test_list.c b/test/unit/test_list.c index 4ed964a7af0..92fdfd8a8e7 100644 --- a/test/unit/test_list.c +++ b/test/unit/test_list.c @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LGPL-3.0-only #include +#include #include "minunit.h" #define BUF_LENGTH 100 @@ -218,6 +219,30 @@ bool test_rz_list_sort5(void) { mu_end; } +bool test_rz_list_from_iter(void) { + HtUP *alpha_ht = ht_up_new(NULL, NULL); + char *unordered_alphabeth[] = { "b", "w", "k", "a", "c", "d", "e", "f", "g", "h", "i", "j", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "x", "y", "z" }; + char *lower[] = { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z" }; + + for (size_t i = 0; i < 26; i++) { + ht_up_insert(alpha_ht, i, (void *)unordered_alphabeth[i]); + } + RzIterator *iter = ht_up_as_iter(alpha_ht); + RzList *list = rz_list_new_from_iterator(iter); + rz_list_sort(list, (RzListComparator)strcmp, NULL); + mu_assert_eq(rz_list_length(list), 26, "Number of elements are off"); + RzListIter *it; + const char *elem; + size_t i = 0; + rz_list_foreach_enum(list, it, elem, i) { + mu_assert_streq(elem, lower[i], "Value mismatched."); + } + ht_up_free(alpha_ht); + rz_iterator_free(iter); + rz_list_free(list); + mu_end; +} + // 3-valued comparator -> {LT,EQ,GT}. static int pintcmp(int *a, int *b, void *user) { return (int)(*a > *b) - (int)(*b > *a); @@ -501,6 +526,7 @@ int all_tests() { mu_run_test(test_rz_list_reverse); mu_run_test(test_rz_list_clone); mu_run_test(test_rz_list_find_ptr); + mu_run_test(test_rz_list_from_iter); return tests_passed != tests_run; }