1 /* Copyright (c) 2003-2004, Roger Dingledine
2 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3 * Copyright (c) 2007-2019, The Tor Project, Inc. */
4 /* See LICENSE for licensing information */
7 * \file smartlist_foreach.h
8 * \brief Macros for iterating over the elements of a smartlist_t.
11 #ifndef TOR_SMARTLIST_FOREACH_H
12 #define TOR_SMARTLIST_FOREACH_H
14 /** Iterate over the items in a smartlist <b>sl</b>, in order. For each item,
15 * assign it to a new local variable of type <b>type</b> named <b>var</b>, and
16 * execute the statements inside the loop body. Inside the loop, the loop
17 * index can be accessed as <b>var</b>_sl_idx and the length of the list can
18 * be accessed as <b>var</b>_sl_len.
20 * NOTE: Do not change the length of the list while the loop is in progress,
21 * unless you adjust the _sl_len variable correspondingly. See second example
26 * smartlist_t *list = smartlist_split("A:B:C", ":", 0, 0);
27 * SMARTLIST_FOREACH_BEGIN(list, char *, cp) {
28 * printf("%d: %s\n", cp_sl_idx, cp);
30 * } SMARTLIST_FOREACH_END(cp);
31 * smartlist_free(list);
34 * Example use (advanced):
36 * SMARTLIST_FOREACH_BEGIN(list, char *, cp) {
37 * if (!strcmp(cp, "junk")) {
39 * SMARTLIST_DEL_CURRENT(list, cp);
41 * } SMARTLIST_FOREACH_END(cp);
44 /* Note: these macros use token pasting, and reach into smartlist internals.
45 * This can make them a little daunting. Here's the approximate unpacking of
46 * the above examples, for entertainment value:
49 * smartlist_t *list = smartlist_split("A:B:C", ":", 0, 0);
51 * int cp_sl_idx, cp_sl_len = smartlist_len(list);
53 * for (cp_sl_idx = 0; cp_sl_idx < cp_sl_len; ++cp_sl_idx) {
54 * cp = smartlist_get(list, cp_sl_idx);
55 * printf("%d: %s\n", cp_sl_idx, cp);
59 * smartlist_free(list);
64 * int cp_sl_idx, cp_sl_len = smartlist_len(list);
66 * for (cp_sl_idx = 0; cp_sl_idx < cp_sl_len; ++cp_sl_idx) {
67 * cp = smartlist_get(list, cp_sl_idx);
68 * if (!strcmp(cp, "junk")) {
70 * smartlist_del(list, cp_sl_idx);
78 #define SMARTLIST_FOREACH_BEGIN(sl, type, var) \
80 int var ## _sl_idx, var ## _sl_len=(sl)->num_used; \
82 for (var ## _sl_idx = 0; var ## _sl_idx < var ## _sl_len; \
84 var = (sl)->list[var ## _sl_idx];
86 /** Iterates over the items in smartlist <b>sl</b> in reverse order, similar to
87 * SMARTLIST_FOREACH_BEGIN
89 * NOTE: This macro is incompatible with SMARTLIST_DEL_CURRENT.
91 #define SMARTLIST_FOREACH_REVERSE_BEGIN(sl, type, var) \
93 int var ## _sl_idx, var ## _sl_len=(sl)->num_used; \
95 for (var ## _sl_idx = var ## _sl_len-1; var ## _sl_idx >= 0; \
97 var = (sl)->list[var ## _sl_idx];
99 #define SMARTLIST_FOREACH_END(var) \
101 (void) var ## _sl_idx; \
105 * An alias for SMARTLIST_FOREACH_BEGIN and SMARTLIST_FOREACH_END, using
106 * <b>cmd</b> as the loop body. This wrapper is here for convenience with
109 * By convention, we do not use this for loops which nest, or for loops over
110 * 10 lines or so. Use SMARTLIST_FOREACH_{BEGIN,END} for those.
112 #define SMARTLIST_FOREACH(sl, type, var, cmd) \
113 SMARTLIST_FOREACH_BEGIN(sl,type,var) { \
115 } SMARTLIST_FOREACH_END(var)
117 /** Helper: While in a SMARTLIST_FOREACH loop over the list <b>sl</b> indexed
118 * with the variable <b>var</b>, remove the current element in a way that
119 * won't confuse the loop. */
120 #define SMARTLIST_DEL_CURRENT(sl, var) \
122 smartlist_del(sl, var ## _sl_idx); \
127 /** Helper: While in a SMARTLIST_FOREACH loop over the list <b>sl</b> indexed
128 * with the variable <b>var</b>, remove the current element in a way that
129 * won't confuse the loop. */
130 #define SMARTLIST_DEL_CURRENT_KEEPORDER(sl, var) \
132 smartlist_del_keeporder(sl, var ## _sl_idx); \
137 /** Helper: While in a SMARTLIST_FOREACH loop over the list <b>sl</b> indexed
138 * with the variable <b>var</b>, replace the current element with <b>val</b>.
139 * Does not deallocate the current value of <b>var</b>.
141 #define SMARTLIST_REPLACE_CURRENT(sl, var, val) \
143 smartlist_set(sl, var ## _sl_idx, val); \
146 #endif /* !defined(TOR_SMARTLIST_FOREACH_H) */