Tor  0.4.7.0-alpha-dev
smartlist_foreach.h
Go to the documentation of this file.
1 /* Copyright (c) 2003-2004, Roger Dingledine
2  * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3  * Copyright (c) 2007-2021, The Tor Project, Inc. */
4 /* See LICENSE for licensing information */
5 
6 /**
7  * \file smartlist_foreach.h
8  * \brief Macros for iterating over the elements of a smartlist_t.
9  **/
10 
11 #ifndef TOR_SMARTLIST_FOREACH_H
12 #define TOR_SMARTLIST_FOREACH_H
13 
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.
19  *
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
22  * below.
23  *
24  * Example use:
25  * <pre>
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);
29  * tor_free(cp);
30  * } SMARTLIST_FOREACH_END(cp);
31  * smartlist_free(list);
32  * </pre>
33  *
34  * Example use (advanced):
35  * <pre>
36  * SMARTLIST_FOREACH_BEGIN(list, char *, cp) {
37  * if (!strcmp(cp, "junk")) {
38  * tor_free(cp);
39  * SMARTLIST_DEL_CURRENT(list, cp);
40  * }
41  * } SMARTLIST_FOREACH_END(cp);
42  * </pre>
43  */
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:
47  *
48  * <pre>
49  * smartlist_t *list = smartlist_split("A:B:C", ":", 0, 0);
50  * {
51  * int cp_sl_idx, cp_sl_len = smartlist_len(list);
52  * char *cp;
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);
56  * tor_free(cp);
57  * }
58  * }
59  * smartlist_free(list);
60  * </pre>
61  *
62  * <pre>
63  * {
64  * int cp_sl_idx, cp_sl_len = smartlist_len(list);
65  * char *cp;
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")) {
69  * tor_free(cp);
70  * smartlist_del(list, cp_sl_idx);
71  * --cp_sl_idx;
72  * --cp_sl_len;
73  * }
74  * }
75  * }
76  * </pre>
77  */
78 #define SMARTLIST_FOREACH_BEGIN(sl, type, var) \
79  STMT_BEGIN \
80  int var ## _sl_idx, var ## _sl_len=(sl)->num_used; \
81  type var; \
82  for (var ## _sl_idx = 0; var ## _sl_idx < var ## _sl_len; \
83  ++var ## _sl_idx) { \
84  var = (sl)->list[var ## _sl_idx];
85 
86 /** Iterates over the items in smartlist <b>sl</b> in reverse order, similar to
87  * SMARTLIST_FOREACH_BEGIN
88  *
89  * NOTE: This macro is incompatible with SMARTLIST_DEL_CURRENT.
90  */
91 #define SMARTLIST_FOREACH_REVERSE_BEGIN(sl, type, var) \
92  STMT_BEGIN \
93  int var ## _sl_idx, var ## _sl_len=(sl)->num_used; \
94  type var; \
95  for (var ## _sl_idx = var ## _sl_len-1; var ## _sl_idx >= 0; \
96  --var ## _sl_idx) { \
97  var = (sl)->list[var ## _sl_idx];
98 
99 #define SMARTLIST_FOREACH_END(var) \
100  var = NULL; \
101  (void) var ## _sl_idx; \
102  } STMT_END
103 
104 /**
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
107  * very short loops.
108  *
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.
111  */
112 #define SMARTLIST_FOREACH(sl, type, var, cmd) \
113  SMARTLIST_FOREACH_BEGIN(sl,type,var) { \
114  cmd; \
115  } SMARTLIST_FOREACH_END(var)
116 
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) \
121  STMT_BEGIN \
122  smartlist_del(sl, var ## _sl_idx); \
123  --var ## _sl_idx; \
124  --var ## _sl_len; \
125  STMT_END
126 
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) \
131  STMT_BEGIN \
132  smartlist_del_keeporder(sl, var ## _sl_idx); \
133  --var ## _sl_idx; \
134  --var ## _sl_len; \
135  STMT_END
136 
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>.
140  */
141 #define SMARTLIST_REPLACE_CURRENT(sl, var, val) \
142  STMT_BEGIN \
143  smartlist_set(sl, var ## _sl_idx, val); \
144  STMT_END
145 
146 #endif /* !defined(TOR_SMARTLIST_FOREACH_H) */