From b1de1e7a77275ad3e8a65d984ff1e9779920e933 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Tue, 26 Jun 2018 12:13:23 -0400 Subject: Extract core part of smartlist code into its own library. The smartlist_core library now contains only the parts of smartlists that are needed for the logging library. This resolves the circularity between "container" and "log". The "containers" library still uses the logging code, and has the higher-level smartlist functions. --- src/lib/container/.may_include | 1 + src/lib/container/smartlist.c | 290 ----------------------------- src/lib/container/smartlist.h | 207 +------------------- src/lib/log/.may_include | 2 +- src/lib/log/torlog.c | 6 +- src/lib/log/util_bug.c | 3 +- src/lib/smartlist_core/.may_include | 7 + src/lib/smartlist_core/include.am | 21 +++ src/lib/smartlist_core/smartlist_core.c | 237 +++++++++++++++++++++++ src/lib/smartlist_core/smartlist_core.h | 95 ++++++++++ src/lib/smartlist_core/smartlist_foreach.h | 128 +++++++++++++ src/lib/smartlist_core/smartlist_split.c | 89 +++++++++ src/lib/smartlist_core/smartlist_split.h | 15 ++ 13 files changed, 603 insertions(+), 498 deletions(-) create mode 100644 src/lib/smartlist_core/.may_include create mode 100644 src/lib/smartlist_core/include.am create mode 100644 src/lib/smartlist_core/smartlist_core.c create mode 100644 src/lib/smartlist_core/smartlist_core.h create mode 100644 src/lib/smartlist_core/smartlist_foreach.h create mode 100644 src/lib/smartlist_core/smartlist_split.c create mode 100644 src/lib/smartlist_core/smartlist_split.h (limited to 'src/lib') diff --git a/src/lib/container/.may_include b/src/lib/container/.may_include index 1114ad8453..2eecb503cd 100644 --- a/src/lib/container/.may_include +++ b/src/lib/container/.may_include @@ -5,6 +5,7 @@ lib/ctime/*.h lib/defs/*.h lib/malloc/*.h lib/err/*.h +lib/smartlist_core/*.h lib/string/*.h lib/testsupport/testsupport.h lib/intmath/*.h diff --git a/src/lib/container/smartlist.c b/src/lib/container/smartlist.c index 3c0844384a..9025cab9f6 100644 --- a/src/lib/container/smartlist.c +++ b/src/lib/container/smartlist.c @@ -9,7 +9,6 @@ * with helper functions to use smartlists. **/ -#include "lib/malloc/util_malloc.h" #include "lib/container/smartlist.h" #include "lib/err/torerr.h" #include "lib/malloc/util_malloc.h" @@ -24,108 +23,6 @@ #include #include -/** All newly allocated smartlists have this capacity. */ -#define SMARTLIST_DEFAULT_CAPACITY 16 - -/** Allocate and return an empty smartlist. - */ -MOCK_IMPL(smartlist_t *, -smartlist_new,(void)) -{ - smartlist_t *sl = tor_malloc(sizeof(smartlist_t)); - sl->num_used = 0; - sl->capacity = SMARTLIST_DEFAULT_CAPACITY; - sl->list = tor_calloc(sizeof(void *), sl->capacity); - return sl; -} - -/** Deallocate a smartlist. Does not release storage associated with the - * list's elements. - */ -MOCK_IMPL(void, -smartlist_free_,(smartlist_t *sl)) -{ - if (!sl) - return; - tor_free(sl->list); - tor_free(sl); -} - -/** Remove all elements from the list. - */ -void -smartlist_clear(smartlist_t *sl) -{ - memset(sl->list, 0, sizeof(void *) * sl->num_used); - sl->num_used = 0; -} - -#if SIZE_MAX < INT_MAX -#error "We don't support systems where size_t is smaller than int." -#endif - -/** Make sure that sl can hold at least size entries. */ -static inline void -smartlist_ensure_capacity(smartlist_t *sl, size_t size) -{ - /* Set MAX_CAPACITY to MIN(INT_MAX, SIZE_MAX / sizeof(void*)) */ -#if (SIZE_MAX/SIZEOF_VOID_P) > INT_MAX -#define MAX_CAPACITY (INT_MAX) -#else -#define MAX_CAPACITY (int)((SIZE_MAX / (sizeof(void*)))) -#endif - - raw_assert(size <= MAX_CAPACITY); - - if (size > (size_t) sl->capacity) { - size_t higher = (size_t) sl->capacity; - if (PREDICT_UNLIKELY(size > MAX_CAPACITY/2)) { - higher = MAX_CAPACITY; - } else { - while (size > higher) - higher *= 2; - } - sl->list = tor_reallocarray(sl->list, sizeof(void *), - ((size_t)higher)); - memset(sl->list + sl->capacity, 0, - sizeof(void *) * (higher - sl->capacity)); - sl->capacity = (int) higher; - } -#undef ASSERT_CAPACITY -#undef MAX_CAPACITY -} - -/** Append element to the end of the list. */ -void -smartlist_add(smartlist_t *sl, void *element) -{ - smartlist_ensure_capacity(sl, ((size_t) sl->num_used)+1); - sl->list[sl->num_used++] = element; -} - -/** Append each element from S2 to the end of S1. */ -void -smartlist_add_all(smartlist_t *s1, const smartlist_t *s2) -{ - size_t new_size = (size_t)s1->num_used + (size_t)s2->num_used; - tor_assert(new_size >= (size_t) s1->num_used); /* check for overflow. */ - smartlist_ensure_capacity(s1, new_size); - memcpy(s1->list + s1->num_used, s2->list, s2->num_used*sizeof(void*)); - tor_assert(new_size <= INT_MAX); /* redundant. */ - s1->num_used = (int) new_size; -} - -/** Append a copy of string to sl */ -void -smartlist_add_strdup(struct smartlist_t *sl, const char *string) -{ - char *copy; - - copy = tor_strdup(string); - - smartlist_add(sl, copy); -} - /** Append the string produced by tor_asprintf(pattern, ...) * to sl. */ void @@ -150,56 +47,6 @@ smartlist_add_vasprintf(struct smartlist_t *sl, const char *pattern, smartlist_add(sl, str); } -/** Remove all elements E from sl such that E==element. Preserve - * the order of any elements before E, but elements after E can be - * rearranged. - */ -void -smartlist_remove(smartlist_t *sl, const void *element) -{ - int i; - if (element == NULL) - return; - for (i=0; i < sl->num_used; i++) - if (sl->list[i] == element) { - sl->list[i] = sl->list[--sl->num_used]; /* swap with the end */ - i--; /* so we process the new i'th element */ - sl->list[sl->num_used] = NULL; - } -} - -/** As smartlist_remove, but do not change the order of - * any elements not removed */ -void -smartlist_remove_keeporder(smartlist_t *sl, const void *element) -{ - int i, j, num_used_orig = sl->num_used; - if (element == NULL) - return; - - for (i=j=0; j < num_used_orig; ++j) { - if (sl->list[j] == element) { - --sl->num_used; - } else { - sl->list[i++] = sl->list[j]; - } - } -} - -/** If sl is nonempty, remove and return the final element. Otherwise, - * return NULL. */ -void * -smartlist_pop_last(smartlist_t *sl) -{ - tor_assert(sl); - if (sl->num_used) { - void *tmp = sl->list[--sl->num_used]; - sl->list[sl->num_used] = NULL; - return tmp; - } else - return NULL; -} - /** Reverse the order of the items in sl. */ void smartlist_reverse(smartlist_t *sl) @@ -232,18 +79,6 @@ smartlist_string_remove(smartlist_t *sl, const char *element) } } -/** Return true iff some element E of sl has E==element. - */ -int -smartlist_contains(const smartlist_t *sl, const void *element) -{ - int i; - for (i=0; i < sl->num_used; i++) - if (sl->list[i] == element) - return 1; - return 0; -} - /** Return true iff sl has some element E such that * !strcmp(E,element) */ @@ -399,131 +234,6 @@ smartlist_subtract(smartlist_t *sl1, const smartlist_t *sl2) smartlist_remove(sl1, sl2->list[i]); } -/** Remove the idxth element of sl; if idx is not the last - * element, swap the last element of sl into the idxth space. - */ -void -smartlist_del(smartlist_t *sl, int idx) -{ - tor_assert(sl); - tor_assert(idx>=0); - tor_assert(idx < sl->num_used); - sl->list[idx] = sl->list[--sl->num_used]; - sl->list[sl->num_used] = NULL; -} - -/** Remove the idxth element of sl; if idx is not the last element, - * moving all subsequent elements back one space. Return the old value - * of the idxth element. - */ -void -smartlist_del_keeporder(smartlist_t *sl, int idx) -{ - tor_assert(sl); - tor_assert(idx>=0); - tor_assert(idx < sl->num_used); - --sl->num_used; - if (idx < sl->num_used) - memmove(sl->list+idx, sl->list+idx+1, sizeof(void*)*(sl->num_used-idx)); - sl->list[sl->num_used] = NULL; -} - -/** Insert the value val as the new idxth element of - * sl, moving all items previously at idx or later - * forward one space. - */ -void -smartlist_insert(smartlist_t *sl, int idx, void *val) -{ - tor_assert(sl); - tor_assert(idx>=0); - tor_assert(idx <= sl->num_used); - if (idx == sl->num_used) { - smartlist_add(sl, val); - } else { - smartlist_ensure_capacity(sl, ((size_t) sl->num_used)+1); - /* Move other elements away */ - if (idx < sl->num_used) - memmove(sl->list + idx + 1, sl->list + idx, - sizeof(void*)*(sl->num_used-idx)); - sl->num_used++; - sl->list[idx] = val; - } -} - -/** - * Split a string str along all occurrences of sep, - * appending the (newly allocated) split strings, in order, to - * sl. Return the number of strings added to sl. - * - * If flags&SPLIT_SKIP_SPACE is true, remove initial and - * trailing space from each entry. - * If flags&SPLIT_IGNORE_BLANK is true, remove any entries - * of length 0. - * If flags&SPLIT_STRIP_SPACE is true, strip spaces from each - * split string. - * - * If max\>0, divide the string into no more than max pieces. If - * sep is NULL, split on any sequence of horizontal space. - */ -int -smartlist_split_string(smartlist_t *sl, const char *str, const char *sep, - int flags, int max) -{ - const char *cp, *end, *next; - int n = 0; - - tor_assert(sl); - tor_assert(str); - - cp = str; - while (1) { - if (flags&SPLIT_SKIP_SPACE) { - while (TOR_ISSPACE(*cp)) ++cp; - } - - if (max>0 && n == max-1) { - end = strchr(cp,'\0'); - } else if (sep) { - end = strstr(cp,sep); - if (!end) - end = strchr(cp,'\0'); - } else { - for (end = cp; *end && *end != '\t' && *end != ' '; ++end) - ; - } - - tor_assert(end); - - if (!*end) { - next = NULL; - } else if (sep) { - next = end+strlen(sep); - } else { - next = end+1; - while (*next == '\t' || *next == ' ') - ++next; - } - - if (flags&SPLIT_SKIP_SPACE) { - while (end > cp && TOR_ISSPACE(*(end-1))) - --end; - } - if (end != cp || !(flags&SPLIT_IGNORE_BLANK)) { - char *string = tor_strndup(cp, end-cp); - if (flags&SPLIT_STRIP_SPACE) - tor_strstrip(string, " "); - smartlist_add(sl, string); - ++n; - } - if (!next) - break; - cp = next; - } - - return n; -} - /** Allocate and return a new string containing the concatenation of * the elements of sl, in order, separated by join. If * terminate is true, also terminate the string with join. diff --git a/src/lib/container/smartlist.h b/src/lib/container/smartlist.h index c202e134f9..76ecbda0a2 100644 --- a/src/lib/container/smartlist.h +++ b/src/lib/container/smartlist.h @@ -6,50 +6,19 @@ #ifndef TOR_SMARTLIST_H #define TOR_SMARTLIST_H -#include #include -#include "lib/cc/compat_compiler.h" -#include "lib/cc/torint.h" -#include "lib/testsupport/testsupport.h" +#include "lib/smartlist_core/smartlist_core.h" +#include "lib/smartlist_core/smartlist_foreach.h" +#include "lib/smartlist_core/smartlist_split.h" -/** A resizeable list of pointers, with associated helpful functionality. - * - * The members of this struct are exposed only so that macros and inlines can - * use them; all access to smartlist internals should go through the functions - * and macros defined here. - **/ -typedef struct smartlist_t { - /** @{ */ - /** list has enough capacity to store exactly capacity elements - * before it needs to be resized. Only the first num_used (\<= - * capacity) elements point to valid data. - */ - void **list; - int num_used; - int capacity; - /** @} */ -} smartlist_t; - -MOCK_DECL(smartlist_t *, smartlist_new, (void)); -MOCK_DECL(void, smartlist_free_, (smartlist_t *sl)); -#define smartlist_free(sl) FREE_AND_NULL(smartlist_t, smartlist_free_, (sl)) - -void smartlist_clear(smartlist_t *sl); -void smartlist_add(smartlist_t *sl, void *element); -void smartlist_add_all(smartlist_t *sl, const smartlist_t *s2); -void smartlist_add_strdup(struct smartlist_t *sl, const char *string); void smartlist_add_asprintf(struct smartlist_t *sl, const char *pattern, ...) CHECK_PRINTF(2, 3); void smartlist_add_vasprintf(struct smartlist_t *sl, const char *pattern, va_list args) CHECK_PRINTF(2, 0); -void smartlist_remove(smartlist_t *sl, const void *element); -void smartlist_remove_keeporder(smartlist_t *sl, const void *element); -void *smartlist_pop_last(smartlist_t *sl); void smartlist_reverse(smartlist_t *sl); void smartlist_string_remove(smartlist_t *sl, const char *element); -int smartlist_contains(const smartlist_t *sl, const void *element); int smartlist_contains_string(const smartlist_t *sl, const char *element); int smartlist_pos(const smartlist_t *sl, const void *element); int smartlist_string_pos(const smartlist_t *, const char *elt); @@ -62,52 +31,6 @@ int smartlist_overlap(const smartlist_t *sl1, const smartlist_t *sl2); void smartlist_intersect(smartlist_t *sl1, const smartlist_t *sl2); void smartlist_subtract(smartlist_t *sl1, const smartlist_t *sl2); -/* smartlist_choose() is defined in crypto.[ch] */ -#ifdef DEBUG_SMARTLIST -#include "lib/err/torerr.h" -#include -/** Return the number of items in sl. - */ -static inline int smartlist_len(const smartlist_t *sl); -static inline int smartlist_len(const smartlist_t *sl) { - raw_assert(sl); - return (sl)->num_used; -} -/** Return the idxth element of sl. - */ -static inline void *smartlist_get(const smartlist_t *sl, int idx); -static inline void *smartlist_get(const smartlist_t *sl, int idx) { - raw_assert(sl); - raw_assert(idx>=0); - raw_assert(sl->num_used > idx); - return sl->list[idx]; -} -static inline void smartlist_set(smartlist_t *sl, int idx, void *val) { - raw_assert(sl); - raw_assert(idx>=0); - raw_assert(sl->num_used > idx); - sl->list[idx] = val; -} -#else /* !(defined(DEBUG_SMARTLIST)) */ -#define smartlist_len(sl) ((sl)->num_used) -#define smartlist_get(sl, idx) ((sl)->list[idx]) -#define smartlist_set(sl, idx, val) ((sl)->list[idx] = (val)) -#endif /* defined(DEBUG_SMARTLIST) */ - -/** Exchange the elements at indices idx1 and idx2 of the - * smartlist sl. */ -static inline void smartlist_swap(smartlist_t *sl, int idx1, int idx2) -{ - if (idx1 != idx2) { - void *elt = smartlist_get(sl, idx1); - smartlist_set(sl, idx1, smartlist_get(sl, idx2)); - smartlist_set(sl, idx2, elt); - } -} - -void smartlist_del(smartlist_t *sl, int idx); -void smartlist_del_keeporder(smartlist_t *sl, int idx); -void smartlist_insert(smartlist_t *sl, int idx, void *val); void smartlist_sort(smartlist_t *sl, int (*compare)(const void **a, const void **b)); void *smartlist_get_most_frequent_(const smartlist_t *sl, @@ -153,136 +76,12 @@ void smartlist_pqueue_assert_ok(smartlist_t *sl, int (*compare)(const void *a, const void *b), int idx_field_offset); -#define SPLIT_SKIP_SPACE 0x01 -#define SPLIT_IGNORE_BLANK 0x02 -#define SPLIT_STRIP_SPACE 0x04 -int smartlist_split_string(smartlist_t *sl, const char *str, const char *sep, - int flags, int max); char *smartlist_join_strings(smartlist_t *sl, const char *join, int terminate, size_t *len_out) ATTR_MALLOC; char *smartlist_join_strings2(smartlist_t *sl, const char *join, size_t join_len, int terminate, size_t *len_out) ATTR_MALLOC; -/** Iterate over the items in a smartlist sl, in order. For each item, - * assign it to a new local variable of type type named var, and - * execute the statements inside the loop body. Inside the loop, the loop - * index can be accessed as var_sl_idx and the length of the list can - * be accessed as var_sl_len. - * - * NOTE: Do not change the length of the list while the loop is in progress, - * unless you adjust the _sl_len variable correspondingly. See second example - * below. - * - * Example use: - *
- *   smartlist_t *list = smartlist_split("A:B:C", ":", 0, 0);
- *   SMARTLIST_FOREACH_BEGIN(list, char *, cp) {
- *     printf("%d: %s\n", cp_sl_idx, cp);
- *     tor_free(cp);
- *   } SMARTLIST_FOREACH_END(cp);
- *   smartlist_free(list);
- * 
- * - * Example use (advanced): - *
- *   SMARTLIST_FOREACH_BEGIN(list, char *, cp) {
- *     if (!strcmp(cp, "junk")) {
- *       tor_free(cp);
- *       SMARTLIST_DEL_CURRENT(list, cp);
- *     }
- *   } SMARTLIST_FOREACH_END(cp);
- * 
- */ -/* Note: these macros use token pasting, and reach into smartlist internals. - * This can make them a little daunting. Here's the approximate unpacking of - * the above examples, for entertainment value: - * - *
- * smartlist_t *list = smartlist_split("A:B:C", ":", 0, 0);
- * {
- *   int cp_sl_idx, cp_sl_len = smartlist_len(list);
- *   char *cp;
- *   for (cp_sl_idx = 0; cp_sl_idx < cp_sl_len; ++cp_sl_idx) {
- *     cp = smartlist_get(list, cp_sl_idx);
- *     printf("%d: %s\n", cp_sl_idx, cp);
- *     tor_free(cp);
- *   }
- * }
- * smartlist_free(list);
- * 
- * - *
- * {
- *   int cp_sl_idx, cp_sl_len = smartlist_len(list);
- *   char *cp;
- *   for (cp_sl_idx = 0; cp_sl_idx < cp_sl_len; ++cp_sl_idx) {
- *     cp = smartlist_get(list, cp_sl_idx);
- *     if (!strcmp(cp, "junk")) {
- *       tor_free(cp);
- *       smartlist_del(list, cp_sl_idx);
- *       --cp_sl_idx;
- *       --cp_sl_len;
- *     }
- *   }
- * }
- * 
- */ -#define SMARTLIST_FOREACH_BEGIN(sl, type, var) \ - STMT_BEGIN \ - int var ## _sl_idx, var ## _sl_len=(sl)->num_used; \ - type var; \ - for (var ## _sl_idx = 0; var ## _sl_idx < var ## _sl_len; \ - ++var ## _sl_idx) { \ - var = (sl)->list[var ## _sl_idx]; - -#define SMARTLIST_FOREACH_END(var) \ - var = NULL; \ - (void) var ## _sl_idx; \ - } STMT_END - -/** - * An alias for SMARTLIST_FOREACH_BEGIN and SMARTLIST_FOREACH_END, using - * cmd as the loop body. This wrapper is here for convenience with - * very short loops. - * - * By convention, we do not use this for loops which nest, or for loops over - * 10 lines or so. Use SMARTLIST_FOREACH_{BEGIN,END} for those. - */ -#define SMARTLIST_FOREACH(sl, type, var, cmd) \ - SMARTLIST_FOREACH_BEGIN(sl,type,var) { \ - cmd; \ - } SMARTLIST_FOREACH_END(var) - -/** Helper: While in a SMARTLIST_FOREACH loop over the list sl indexed - * with the variable var, remove the current element in a way that - * won't confuse the loop. */ -#define SMARTLIST_DEL_CURRENT(sl, var) \ - STMT_BEGIN \ - smartlist_del(sl, var ## _sl_idx); \ - --var ## _sl_idx; \ - --var ## _sl_len; \ - STMT_END - -/** Helper: While in a SMARTLIST_FOREACH loop over the list sl indexed - * with the variable var, remove the current element in a way that - * won't confuse the loop. */ -#define SMARTLIST_DEL_CURRENT_KEEPORDER(sl, var) \ - STMT_BEGIN \ - smartlist_del_keeporder(sl, var ## _sl_idx); \ - --var ## _sl_idx; \ - --var ## _sl_len; \ - STMT_END - -/** Helper: While in a SMARTLIST_FOREACH loop over the list sl indexed - * with the variable var, replace the current element with val. - * Does not deallocate the current value of var. - */ -#define SMARTLIST_REPLACE_CURRENT(sl, var, val) \ - STMT_BEGIN \ - smartlist_set(sl, var ## _sl_idx, val); \ - STMT_END - /* Helper: Given two lists of items, possibly of different types, such that * both lists are sorted on some common field (as determined by a comparison * expression cmpexpr), and such that one list (sl1) has no diff --git a/src/lib/log/.may_include b/src/lib/log/.may_include index 36a164cce0..852173aab3 100644 --- a/src/lib/log/.may_include +++ b/src/lib/log/.may_include @@ -1,7 +1,7 @@ orconfig.h lib/cc/*.h -lib/container/smartlist.h +lib/smartlist_core/*.h lib/err/*.h lib/fdio/*.h lib/intmath/*.h diff --git a/src/lib/log/torlog.c b/src/lib/log/torlog.c index 5709dd8199..bffffbf1bd 100644 --- a/src/lib/log/torlog.c +++ b/src/lib/log/torlog.c @@ -5,7 +5,7 @@ /* See LICENSE for licensing information */ /** - * \file log.c + * \file torlog.c * \brief Functions to send messages to log files or the console. **/ @@ -34,7 +34,9 @@ #include "lib/log/torlog.h" #include "lib/log/ratelim.h" #include "lib/lock/compat_mutex.h" -#include "lib/container/smartlist.h" +#include "lib/smartlist_core/smartlist_core.h" +#include "lib/smartlist_core/smartlist_foreach.h" +#include "lib/smartlist_core/smartlist_split.h" #include "lib/err/torerr.h" #include "lib/intmath/bits.h" #include "lib/string/compat_string.h" diff --git a/src/lib/log/util_bug.c b/src/lib/log/util_bug.c index 161b65e0bf..78af08f022 100644 --- a/src/lib/log/util_bug.c +++ b/src/lib/log/util_bug.c @@ -12,7 +12,8 @@ #include "lib/log/torlog.h" #include "lib/err/backtrace.h" #ifdef TOR_UNIT_TESTS -#include "lib/container/smartlist.h" +#include "lib/smartlist_core/smartlist_core.h" +#include "lib/smartlist_core/smartlist_foreach.h" #endif #include "lib/malloc/util_malloc.h" #include "lib/string/printf.h" diff --git a/src/lib/smartlist_core/.may_include b/src/lib/smartlist_core/.may_include new file mode 100644 index 0000000000..a8507761a4 --- /dev/null +++ b/src/lib/smartlist_core/.may_include @@ -0,0 +1,7 @@ +orconfig.h +lib/cc/*.h +lib/malloc/*.h +lib/err/*.h +lib/string/*.h +lib/smartlist_core/*.h +lib/testsupport/testsupport.h diff --git a/src/lib/smartlist_core/include.am b/src/lib/smartlist_core/include.am new file mode 100644 index 0000000000..9ee93fdee7 --- /dev/null +++ b/src/lib/smartlist_core/include.am @@ -0,0 +1,21 @@ + +noinst_LIBRARIES += src/lib/libtor-smartlist-core.a + +if UNITTESTS_ENABLED +noinst_LIBRARIES += src/lib/libtor-smartlist-core-testing.a +endif + +src_lib_libtor_smartlist_core_a_SOURCES = \ + src/lib/smartlist_core/smartlist_core.c \ + src/lib/smartlist_core/smartlist_split.c + +src_lib_libtor_smartlist_core_testing_a_SOURCES = \ + $(src_lib_libtor_smartlist_core_a_SOURCES) +src_lib_libtor_smartlist_core_testing_a_CPPFLAGS = \ + $(AM_CPPFLAGS) $(TEST_CPPFLAGS) +src_lib_libtor_smartlist_core_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS) + +noinst_HEADERS += \ + src/lib/smartlist_core/smartlist_core.h \ + src/lib/smartlist_core/smartlist_foreach.h \ + src/lib/smartlist_core/smartlist_split.h diff --git a/src/lib/smartlist_core/smartlist_core.c b/src/lib/smartlist_core/smartlist_core.c new file mode 100644 index 0000000000..ca5c5f0bf1 --- /dev/null +++ b/src/lib/smartlist_core/smartlist_core.c @@ -0,0 +1,237 @@ +/* Copyright (c) 2003-2004, Roger Dingledine + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2018, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file smartlist_core.c + * \brief Implements the core functionality of a smartlist (a resizeable + * dynamic array). For more functionality and helper functions, see the + * container library. + **/ + +#include "lib/err/torerr.h" +#include "lib/malloc/util_malloc.h" +#include "lib/smartlist_core/smartlist_core.h" + +#define tor_assert raw_assert + +#include +#include + +/** All newly allocated smartlists have this capacity. */ +#define SMARTLIST_DEFAULT_CAPACITY 16 + +/** Allocate and return an empty smartlist. + */ +MOCK_IMPL(smartlist_t *, +smartlist_new,(void)) +{ + smartlist_t *sl = tor_malloc(sizeof(smartlist_t)); + sl->num_used = 0; + sl->capacity = SMARTLIST_DEFAULT_CAPACITY; + sl->list = tor_calloc(sizeof(void *), sl->capacity); + return sl; +} + +/** Deallocate a smartlist. Does not release storage associated with the + * list's elements. + */ +MOCK_IMPL(void, +smartlist_free_,(smartlist_t *sl)) +{ + if (!sl) + return; + tor_free(sl->list); + tor_free(sl); +} + +/** Remove all elements from the list. + */ +void +smartlist_clear(smartlist_t *sl) +{ + memset(sl->list, 0, sizeof(void *) * sl->num_used); + sl->num_used = 0; +} + +#if SIZE_MAX < INT_MAX +#error "We don't support systems where size_t is smaller than int." +#endif + +/** Make sure that sl can hold at least size entries. */ +static inline void +smartlist_ensure_capacity(smartlist_t *sl, size_t size) +{ + /* Set MAX_CAPACITY to MIN(INT_MAX, SIZE_MAX / sizeof(void*)) */ +#if (SIZE_MAX/SIZEOF_VOID_P) > INT_MAX +#define MAX_CAPACITY (INT_MAX) +#else +#define MAX_CAPACITY (int)((SIZE_MAX / (sizeof(void*)))) +#endif + + raw_assert(size <= MAX_CAPACITY); + + if (size > (size_t) sl->capacity) { + size_t higher = (size_t) sl->capacity; + if (PREDICT_UNLIKELY(size > MAX_CAPACITY/2)) { + higher = MAX_CAPACITY; + } else { + while (size > higher) + higher *= 2; + } + sl->list = tor_reallocarray(sl->list, sizeof(void *), + ((size_t)higher)); + memset(sl->list + sl->capacity, 0, + sizeof(void *) * (higher - sl->capacity)); + sl->capacity = (int) higher; + } +#undef ASSERT_CAPACITY +#undef MAX_CAPACITY +} + +/** Append element to the end of the list. */ +void +smartlist_add(smartlist_t *sl, void *element) +{ + smartlist_ensure_capacity(sl, ((size_t) sl->num_used)+1); + sl->list[sl->num_used++] = element; +} + +/** Append each element from S2 to the end of S1. */ +void +smartlist_add_all(smartlist_t *s1, const smartlist_t *s2) +{ + size_t new_size = (size_t)s1->num_used + (size_t)s2->num_used; + tor_assert(new_size >= (size_t) s1->num_used); /* check for overflow. */ + smartlist_ensure_capacity(s1, new_size); + memcpy(s1->list + s1->num_used, s2->list, s2->num_used*sizeof(void*)); + tor_assert(new_size <= INT_MAX); /* redundant. */ + s1->num_used = (int) new_size; +} + +/** Append a copy of string to sl */ +void +smartlist_add_strdup(struct smartlist_t *sl, const char *string) +{ + char *copy; + + copy = tor_strdup(string); + + smartlist_add(sl, copy); +} + +/** Remove all elements E from sl such that E==element. Preserve + * the order of any elements before E, but elements after E can be + * rearranged. + */ +void +smartlist_remove(smartlist_t *sl, const void *element) +{ + int i; + if (element == NULL) + return; + for (i=0; i < sl->num_used; i++) + if (sl->list[i] == element) { + sl->list[i] = sl->list[--sl->num_used]; /* swap with the end */ + i--; /* so we process the new i'th element */ + sl->list[sl->num_used] = NULL; + } +} + +/** As smartlist_remove, but do not change the order of + * any elements not removed */ +void +smartlist_remove_keeporder(smartlist_t *sl, const void *element) +{ + int i, j, num_used_orig = sl->num_used; + if (element == NULL) + return; + + for (i=j=0; j < num_used_orig; ++j) { + if (sl->list[j] == element) { + --sl->num_used; + } else { + sl->list[i++] = sl->list[j]; + } + } +} + +/** If sl is nonempty, remove and return the final element. Otherwise, + * return NULL. */ +void * +smartlist_pop_last(smartlist_t *sl) +{ + tor_assert(sl); + if (sl->num_used) { + void *tmp = sl->list[--sl->num_used]; + sl->list[sl->num_used] = NULL; + return tmp; + } else + return NULL; +} + + +/** Return true iff some element E of sl has E==element. + */ +int +smartlist_contains(const smartlist_t *sl, const void *element) +{ + int i; + for (i=0; i < sl->num_used; i++) + if (sl->list[i] == element) + return 1; + return 0; +} + +/** Remove the idxth element of sl; if idx is not the last + * element, swap the last element of sl into the idxth space. + */ +void +smartlist_del(smartlist_t *sl, int idx) +{ + tor_assert(sl); + tor_assert(idx>=0); + tor_assert(idx < sl->num_used); + sl->list[idx] = sl->list[--sl->num_used]; + sl->list[sl->num_used] = NULL; +} + +/** Remove the idxth element of sl; if idx is not the last element, + * moving all subsequent elements back one space. Return the old value + * of the idxth element. + */ +void +smartlist_del_keeporder(smartlist_t *sl, int idx) +{ + tor_assert(sl); + tor_assert(idx>=0); + tor_assert(idx < sl->num_used); + --sl->num_used; + if (idx < sl->num_used) + memmove(sl->list+idx, sl->list+idx+1, sizeof(void*)*(sl->num_used-idx)); + sl->list[sl->num_used] = NULL; +} + +/** Insert the value val as the new idxth element of + * sl, moving all items previously at idx or later + * forward one space. + */ +void +smartlist_insert(smartlist_t *sl, int idx, void *val) +{ + tor_assert(sl); + tor_assert(idx>=0); + tor_assert(idx <= sl->num_used); + if (idx == sl->num_used) { + smartlist_add(sl, val); + } else { + smartlist_ensure_capacity(sl, ((size_t) sl->num_used)+1); + /* Move other elements away */ + if (idx < sl->num_used) + memmove(sl->list + idx + 1, sl->list + idx, + sizeof(void*)*(sl->num_used-idx)); + sl->num_used++; + sl->list[idx] = val; + } +} diff --git a/src/lib/smartlist_core/smartlist_core.h b/src/lib/smartlist_core/smartlist_core.h new file mode 100644 index 0000000000..b1adf2ebdb --- /dev/null +++ b/src/lib/smartlist_core/smartlist_core.h @@ -0,0 +1,95 @@ +/* Copyright (c) 2003-2004, Roger Dingledine + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2018, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#ifndef TOR_SMARTLIST_CORE_H +#define TOR_SMARTLIST_CORE_H + +#include + +#include "lib/cc/compat_compiler.h" +#include "lib/cc/torint.h" +#include "lib/testsupport/testsupport.h" + +/** A resizeable list of pointers, with associated helpful functionality. + * + * The members of this struct are exposed only so that macros and inlines can + * use them; all access to smartlist internals should go through the functions + * and macros defined here. + **/ +typedef struct smartlist_t { + /** @{ */ + /** list has enough capacity to store exactly capacity elements + * before it needs to be resized. Only the first num_used (\<= + * capacity) elements point to valid data. + */ + void **list; + int num_used; + int capacity; + /** @} */ +} smartlist_t; + +MOCK_DECL(smartlist_t *, smartlist_new, (void)); +MOCK_DECL(void, smartlist_free_, (smartlist_t *sl)); +#define smartlist_free(sl) FREE_AND_NULL(smartlist_t, smartlist_free_, (sl)) + +void smartlist_clear(smartlist_t *sl); +void smartlist_add(smartlist_t *sl, void *element); +void smartlist_add_all(smartlist_t *sl, const smartlist_t *s2); +void smartlist_add_strdup(struct smartlist_t *sl, const char *string); + +void smartlist_remove(smartlist_t *sl, const void *element); +void smartlist_remove_keeporder(smartlist_t *sl, const void *element); +void *smartlist_pop_last(smartlist_t *sl); + +int smartlist_contains(const smartlist_t *sl, const void *element); + +/* smartlist_choose() is defined in crypto.[ch] */ +#ifdef DEBUG_SMARTLIST +#include "lib/err/torerr.h" +#include +/** Return the number of items in sl. + */ +static inline int smartlist_len(const smartlist_t *sl); +static inline int smartlist_len(const smartlist_t *sl) { + raw_assert(sl); + return (sl)->num_used; +} +/** Return the idxth element of sl. + */ +static inline void *smartlist_get(const smartlist_t *sl, int idx); +static inline void *smartlist_get(const smartlist_t *sl, int idx) { + raw_assert(sl); + raw_assert(idx>=0); + raw_assert(sl->num_used > idx); + return sl->list[idx]; +} +static inline void smartlist_set(smartlist_t *sl, int idx, void *val) { + raw_assert(sl); + raw_assert(idx>=0); + raw_assert(sl->num_used > idx); + sl->list[idx] = val; +} +#else /* !(defined(DEBUG_SMARTLIST)) */ +#define smartlist_len(sl) ((sl)->num_used) +#define smartlist_get(sl, idx) ((sl)->list[idx]) +#define smartlist_set(sl, idx, val) ((sl)->list[idx] = (val)) +#endif /* defined(DEBUG_SMARTLIST) */ + +/** Exchange the elements at indices idx1 and idx2 of the + * smartlist sl. */ +static inline void smartlist_swap(smartlist_t *sl, int idx1, int idx2) +{ + if (idx1 != idx2) { + void *elt = smartlist_get(sl, idx1); + smartlist_set(sl, idx1, smartlist_get(sl, idx2)); + smartlist_set(sl, idx2, elt); + } +} + +void smartlist_del(smartlist_t *sl, int idx); +void smartlist_del_keeporder(smartlist_t *sl, int idx); +void smartlist_insert(smartlist_t *sl, int idx, void *val); + +#endif /* !defined(TOR_CONTAINER_H) */ diff --git a/src/lib/smartlist_core/smartlist_foreach.h b/src/lib/smartlist_core/smartlist_foreach.h new file mode 100644 index 0000000000..4bef36d99c --- /dev/null +++ b/src/lib/smartlist_core/smartlist_foreach.h @@ -0,0 +1,128 @@ +/* Copyright (c) 2003-2004, Roger Dingledine + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2018, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#ifndef TOR_SMARTLIST_FOREACH_H +#define TOR_SMARTLIST_FOREACH_H + +/** Iterate over the items in a smartlist sl, in order. For each item, + * assign it to a new local variable of type type named var, and + * execute the statements inside the loop body. Inside the loop, the loop + * index can be accessed as var_sl_idx and the length of the list can + * be accessed as var_sl_len. + * + * NOTE: Do not change the length of the list while the loop is in progress, + * unless you adjust the _sl_len variable correspondingly. See second example + * below. + * + * Example use: + *
+ *   smartlist_t *list = smartlist_split("A:B:C", ":", 0, 0);
+ *   SMARTLIST_FOREACH_BEGIN(list, char *, cp) {
+ *     printf("%d: %s\n", cp_sl_idx, cp);
+ *     tor_free(cp);
+ *   } SMARTLIST_FOREACH_END(cp);
+ *   smartlist_free(list);
+ * 
+ * + * Example use (advanced): + *
+ *   SMARTLIST_FOREACH_BEGIN(list, char *, cp) {
+ *     if (!strcmp(cp, "junk")) {
+ *       tor_free(cp);
+ *       SMARTLIST_DEL_CURRENT(list, cp);
+ *     }
+ *   } SMARTLIST_FOREACH_END(cp);
+ * 
+ */ +/* Note: these macros use token pasting, and reach into smartlist internals. + * This can make them a little daunting. Here's the approximate unpacking of + * the above examples, for entertainment value: + * + *
+ * smartlist_t *list = smartlist_split("A:B:C", ":", 0, 0);
+ * {
+ *   int cp_sl_idx, cp_sl_len = smartlist_len(list);
+ *   char *cp;
+ *   for (cp_sl_idx = 0; cp_sl_idx < cp_sl_len; ++cp_sl_idx) {
+ *     cp = smartlist_get(list, cp_sl_idx);
+ *     printf("%d: %s\n", cp_sl_idx, cp);
+ *     tor_free(cp);
+ *   }
+ * }
+ * smartlist_free(list);
+ * 
+ * + *
+ * {
+ *   int cp_sl_idx, cp_sl_len = smartlist_len(list);
+ *   char *cp;
+ *   for (cp_sl_idx = 0; cp_sl_idx < cp_sl_len; ++cp_sl_idx) {
+ *     cp = smartlist_get(list, cp_sl_idx);
+ *     if (!strcmp(cp, "junk")) {
+ *       tor_free(cp);
+ *       smartlist_del(list, cp_sl_idx);
+ *       --cp_sl_idx;
+ *       --cp_sl_len;
+ *     }
+ *   }
+ * }
+ * 
+ */ +#define SMARTLIST_FOREACH_BEGIN(sl, type, var) \ + STMT_BEGIN \ + int var ## _sl_idx, var ## _sl_len=(sl)->num_used; \ + type var; \ + for (var ## _sl_idx = 0; var ## _sl_idx < var ## _sl_len; \ + ++var ## _sl_idx) { \ + var = (sl)->list[var ## _sl_idx]; + +#define SMARTLIST_FOREACH_END(var) \ + var = NULL; \ + (void) var ## _sl_idx; \ + } STMT_END + +/** + * An alias for SMARTLIST_FOREACH_BEGIN and SMARTLIST_FOREACH_END, using + * cmd as the loop body. This wrapper is here for convenience with + * very short loops. + * + * By convention, we do not use this for loops which nest, or for loops over + * 10 lines or so. Use SMARTLIST_FOREACH_{BEGIN,END} for those. + */ +#define SMARTLIST_FOREACH(sl, type, var, cmd) \ + SMARTLIST_FOREACH_BEGIN(sl,type,var) { \ + cmd; \ + } SMARTLIST_FOREACH_END(var) + +/** Helper: While in a SMARTLIST_FOREACH loop over the list sl indexed + * with the variable var, remove the current element in a way that + * won't confuse the loop. */ +#define SMARTLIST_DEL_CURRENT(sl, var) \ + STMT_BEGIN \ + smartlist_del(sl, var ## _sl_idx); \ + --var ## _sl_idx; \ + --var ## _sl_len; \ + STMT_END + +/** Helper: While in a SMARTLIST_FOREACH loop over the list sl indexed + * with the variable var, remove the current element in a way that + * won't confuse the loop. */ +#define SMARTLIST_DEL_CURRENT_KEEPORDER(sl, var) \ + STMT_BEGIN \ + smartlist_del_keeporder(sl, var ## _sl_idx); \ + --var ## _sl_idx; \ + --var ## _sl_len; \ + STMT_END + +/** Helper: While in a SMARTLIST_FOREACH loop over the list sl indexed + * with the variable var, replace the current element with val. + * Does not deallocate the current value of var. + */ +#define SMARTLIST_REPLACE_CURRENT(sl, var, val) \ + STMT_BEGIN \ + smartlist_set(sl, var ## _sl_idx, val); \ + STMT_END + +#endif /* !defined(TOR_SMARTLIST_FOREACH_H) */ diff --git a/src/lib/smartlist_core/smartlist_split.c b/src/lib/smartlist_core/smartlist_split.c new file mode 100644 index 0000000000..e24a742c21 --- /dev/null +++ b/src/lib/smartlist_core/smartlist_split.c @@ -0,0 +1,89 @@ +/* Copyright (c) 2003-2004, Roger Dingledine + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2018, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#include "lib/smartlist_core/smartlist_core.h" +#include "lib/smartlist_core/smartlist_split.h" + +#include "lib/err/torerr.h" +#include "lib/string/util_string.h" +#include "lib/string/compat_ctype.h" +#include "lib/malloc/util_malloc.h" + +#include + +#define tor_assert raw_assert + +/** + * Split a string str along all occurrences of sep, + * appending the (newly allocated) split strings, in order, to + * sl. Return the number of strings added to sl. + * + * If flags&SPLIT_SKIP_SPACE is true, remove initial and + * trailing space from each entry. + * If flags&SPLIT_IGNORE_BLANK is true, remove any entries + * of length 0. + * If flags&SPLIT_STRIP_SPACE is true, strip spaces from each + * split string. + * + * If max\>0, divide the string into no more than max pieces. If + * sep is NULL, split on any sequence of horizontal space. + */ +int +smartlist_split_string(smartlist_t *sl, const char *str, const char *sep, + int flags, int max) +{ + const char *cp, *end, *next; + int n = 0; + + tor_assert(sl); + tor_assert(str); + + cp = str; + while (1) { + if (flags&SPLIT_SKIP_SPACE) { + while (TOR_ISSPACE(*cp)) ++cp; + } + + if (max>0 && n == max-1) { + end = strchr(cp,'\0'); + } else if (sep) { + end = strstr(cp,sep); + if (!end) + end = strchr(cp,'\0'); + } else { + for (end = cp; *end && *end != '\t' && *end != ' '; ++end) + ; + } + + tor_assert(end); + + if (!*end) { + next = NULL; + } else if (sep) { + next = end+strlen(sep); + } else { + next = end+1; + while (*next == '\t' || *next == ' ') + ++next; + } + + if (flags&SPLIT_SKIP_SPACE) { + while (end > cp && TOR_ISSPACE(*(end-1))) + --end; + } + if (end != cp || !(flags&SPLIT_IGNORE_BLANK)) { + char *string = tor_strndup(cp, end-cp); + if (flags&SPLIT_STRIP_SPACE) + tor_strstrip(string, " "); + smartlist_add(sl, string); + ++n; + } + if (!next) + break; + cp = next; + } + + return n; +} diff --git a/src/lib/smartlist_core/smartlist_split.h b/src/lib/smartlist_core/smartlist_split.h new file mode 100644 index 0000000000..8ed2abafb8 --- /dev/null +++ b/src/lib/smartlist_core/smartlist_split.h @@ -0,0 +1,15 @@ +/* Copyright (c) 2003-2004, Roger Dingledine + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2018, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#ifndef TOR_SMARTLIST_SPLIT_H +#define TOR_SMARTLIST_SPLIT_H + +#define SPLIT_SKIP_SPACE 0x01 +#define SPLIT_IGNORE_BLANK 0x02 +#define SPLIT_STRIP_SPACE 0x04 +int smartlist_split_string(smartlist_t *sl, const char *str, const char *sep, + int flags, int max); + +#endif -- cgit v1.2.3-54-g00ecf From d7bd8cf3b6d70f3014bb1140d0d018f94fedb178 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Tue, 26 Jun 2018 12:16:04 -0400 Subject: Use raw_assert directly in smartlist_core I had previously added a "#define tor_assert raw_assert" here, to make code movement in the previous commit more clear. --- src/lib/smartlist_core/smartlist_core.c | 26 ++++++++++++-------------- src/lib/smartlist_core/smartlist_split.c | 8 +++----- 2 files changed, 15 insertions(+), 19 deletions(-) (limited to 'src/lib') diff --git a/src/lib/smartlist_core/smartlist_core.c b/src/lib/smartlist_core/smartlist_core.c index ca5c5f0bf1..aefdd77099 100644 --- a/src/lib/smartlist_core/smartlist_core.c +++ b/src/lib/smartlist_core/smartlist_core.c @@ -14,8 +14,6 @@ #include "lib/malloc/util_malloc.h" #include "lib/smartlist_core/smartlist_core.h" -#define tor_assert raw_assert - #include #include @@ -103,10 +101,10 @@ void smartlist_add_all(smartlist_t *s1, const smartlist_t *s2) { size_t new_size = (size_t)s1->num_used + (size_t)s2->num_used; - tor_assert(new_size >= (size_t) s1->num_used); /* check for overflow. */ + raw_assert(new_size >= (size_t) s1->num_used); /* check for overflow. */ smartlist_ensure_capacity(s1, new_size); memcpy(s1->list + s1->num_used, s2->list, s2->num_used*sizeof(void*)); - tor_assert(new_size <= INT_MAX); /* redundant. */ + raw_assert(new_size <= INT_MAX); /* redundant. */ s1->num_used = (int) new_size; } @@ -162,7 +160,7 @@ smartlist_remove_keeporder(smartlist_t *sl, const void *element) void * smartlist_pop_last(smartlist_t *sl) { - tor_assert(sl); + raw_assert(sl); if (sl->num_used) { void *tmp = sl->list[--sl->num_used]; sl->list[sl->num_used] = NULL; @@ -190,9 +188,9 @@ smartlist_contains(const smartlist_t *sl, const void *element) void smartlist_del(smartlist_t *sl, int idx) { - tor_assert(sl); - tor_assert(idx>=0); - tor_assert(idx < sl->num_used); + raw_assert(sl); + raw_assert(idx>=0); + raw_assert(idx < sl->num_used); sl->list[idx] = sl->list[--sl->num_used]; sl->list[sl->num_used] = NULL; } @@ -204,9 +202,9 @@ smartlist_del(smartlist_t *sl, int idx) void smartlist_del_keeporder(smartlist_t *sl, int idx) { - tor_assert(sl); - tor_assert(idx>=0); - tor_assert(idx < sl->num_used); + raw_assert(sl); + raw_assert(idx>=0); + raw_assert(idx < sl->num_used); --sl->num_used; if (idx < sl->num_used) memmove(sl->list+idx, sl->list+idx+1, sizeof(void*)*(sl->num_used-idx)); @@ -220,9 +218,9 @@ smartlist_del_keeporder(smartlist_t *sl, int idx) void smartlist_insert(smartlist_t *sl, int idx, void *val) { - tor_assert(sl); - tor_assert(idx>=0); - tor_assert(idx <= sl->num_used); + raw_assert(sl); + raw_assert(idx>=0); + raw_assert(idx <= sl->num_used); if (idx == sl->num_used) { smartlist_add(sl, val); } else { diff --git a/src/lib/smartlist_core/smartlist_split.c b/src/lib/smartlist_core/smartlist_split.c index e24a742c21..b9340e7924 100644 --- a/src/lib/smartlist_core/smartlist_split.c +++ b/src/lib/smartlist_core/smartlist_split.c @@ -13,8 +13,6 @@ #include -#define tor_assert raw_assert - /** * Split a string str along all occurrences of sep, * appending the (newly allocated) split strings, in order, to @@ -37,8 +35,8 @@ smartlist_split_string(smartlist_t *sl, const char *str, const char *sep, const char *cp, *end, *next; int n = 0; - tor_assert(sl); - tor_assert(str); + raw_assert(sl); + raw_assert(str); cp = str; while (1) { @@ -57,7 +55,7 @@ smartlist_split_string(smartlist_t *sl, const char *str, const char *sep, ; } - tor_assert(end); + raw_assert(end); if (!*end) { next = NULL; -- cgit v1.2.3-54-g00ecf From 82a7343b061b110cb97e4d804f989bc34ee120c9 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Tue, 26 Jun 2018 12:21:35 -0400 Subject: fixup! Extract core part of smartlist code into its own library. --- src/lib/smartlist_core/smartlist_core.c | 1 - 1 file changed, 1 deletion(-) (limited to 'src/lib') diff --git a/src/lib/smartlist_core/smartlist_core.c b/src/lib/smartlist_core/smartlist_core.c index aefdd77099..b9c5f728ce 100644 --- a/src/lib/smartlist_core/smartlist_core.c +++ b/src/lib/smartlist_core/smartlist_core.c @@ -169,7 +169,6 @@ smartlist_pop_last(smartlist_t *sl) return NULL; } - /** Return true iff some element E of sl has E==element. */ int -- cgit v1.2.3-54-g00ecf