smartlist_foreach.h 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. /* Copyright (c) 2003-2004, Roger Dingledine
  2. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
  3. * Copyright (c) 2007-2018, The Tor Project, Inc. */
  4. /* See LICENSE for licensing information */
  5. /**
  6. * \file smartlist_foreach.h
  7. * \brief Macros for iterating over the elements of a smartlist_t.
  8. **/
  9. #ifndef TOR_SMARTLIST_FOREACH_H
  10. #define TOR_SMARTLIST_FOREACH_H
  11. /** Iterate over the items in a smartlist <b>sl</b>, in order. For each item,
  12. * assign it to a new local variable of type <b>type</b> named <b>var</b>, and
  13. * execute the statements inside the loop body. Inside the loop, the loop
  14. * index can be accessed as <b>var</b>_sl_idx and the length of the list can
  15. * be accessed as <b>var</b>_sl_len.
  16. *
  17. * NOTE: Do not change the length of the list while the loop is in progress,
  18. * unless you adjust the _sl_len variable correspondingly. See second example
  19. * below.
  20. *
  21. * Example use:
  22. * <pre>
  23. * smartlist_t *list = smartlist_split("A:B:C", ":", 0, 0);
  24. * SMARTLIST_FOREACH_BEGIN(list, char *, cp) {
  25. * printf("%d: %s\n", cp_sl_idx, cp);
  26. * tor_free(cp);
  27. * } SMARTLIST_FOREACH_END(cp);
  28. * smartlist_free(list);
  29. * </pre>
  30. *
  31. * Example use (advanced):
  32. * <pre>
  33. * SMARTLIST_FOREACH_BEGIN(list, char *, cp) {
  34. * if (!strcmp(cp, "junk")) {
  35. * tor_free(cp);
  36. * SMARTLIST_DEL_CURRENT(list, cp);
  37. * }
  38. * } SMARTLIST_FOREACH_END(cp);
  39. * </pre>
  40. */
  41. /* Note: these macros use token pasting, and reach into smartlist internals.
  42. * This can make them a little daunting. Here's the approximate unpacking of
  43. * the above examples, for entertainment value:
  44. *
  45. * <pre>
  46. * smartlist_t *list = smartlist_split("A:B:C", ":", 0, 0);
  47. * {
  48. * int cp_sl_idx, cp_sl_len = smartlist_len(list);
  49. * char *cp;
  50. * for (cp_sl_idx = 0; cp_sl_idx < cp_sl_len; ++cp_sl_idx) {
  51. * cp = smartlist_get(list, cp_sl_idx);
  52. * printf("%d: %s\n", cp_sl_idx, cp);
  53. * tor_free(cp);
  54. * }
  55. * }
  56. * smartlist_free(list);
  57. * </pre>
  58. *
  59. * <pre>
  60. * {
  61. * int cp_sl_idx, cp_sl_len = smartlist_len(list);
  62. * char *cp;
  63. * for (cp_sl_idx = 0; cp_sl_idx < cp_sl_len; ++cp_sl_idx) {
  64. * cp = smartlist_get(list, cp_sl_idx);
  65. * if (!strcmp(cp, "junk")) {
  66. * tor_free(cp);
  67. * smartlist_del(list, cp_sl_idx);
  68. * --cp_sl_idx;
  69. * --cp_sl_len;
  70. * }
  71. * }
  72. * }
  73. * </pre>
  74. */
  75. #define SMARTLIST_FOREACH_BEGIN(sl, type, var) \
  76. STMT_BEGIN \
  77. int var ## _sl_idx, var ## _sl_len=(sl)->num_used; \
  78. type var; \
  79. for (var ## _sl_idx = 0; var ## _sl_idx < var ## _sl_len; \
  80. ++var ## _sl_idx) { \
  81. var = (sl)->list[var ## _sl_idx];
  82. #define SMARTLIST_FOREACH_END(var) \
  83. var = NULL; \
  84. (void) var ## _sl_idx; \
  85. } STMT_END
  86. /**
  87. * An alias for SMARTLIST_FOREACH_BEGIN and SMARTLIST_FOREACH_END, using
  88. * <b>cmd</b> as the loop body. This wrapper is here for convenience with
  89. * very short loops.
  90. *
  91. * By convention, we do not use this for loops which nest, or for loops over
  92. * 10 lines or so. Use SMARTLIST_FOREACH_{BEGIN,END} for those.
  93. */
  94. #define SMARTLIST_FOREACH(sl, type, var, cmd) \
  95. SMARTLIST_FOREACH_BEGIN(sl,type,var) { \
  96. cmd; \
  97. } SMARTLIST_FOREACH_END(var)
  98. /** Helper: While in a SMARTLIST_FOREACH loop over the list <b>sl</b> indexed
  99. * with the variable <b>var</b>, remove the current element in a way that
  100. * won't confuse the loop. */
  101. #define SMARTLIST_DEL_CURRENT(sl, var) \
  102. STMT_BEGIN \
  103. smartlist_del(sl, var ## _sl_idx); \
  104. --var ## _sl_idx; \
  105. --var ## _sl_len; \
  106. STMT_END
  107. /** Helper: While in a SMARTLIST_FOREACH loop over the list <b>sl</b> indexed
  108. * with the variable <b>var</b>, remove the current element in a way that
  109. * won't confuse the loop. */
  110. #define SMARTLIST_DEL_CURRENT_KEEPORDER(sl, var) \
  111. STMT_BEGIN \
  112. smartlist_del_keeporder(sl, var ## _sl_idx); \
  113. --var ## _sl_idx; \
  114. --var ## _sl_len; \
  115. STMT_END
  116. /** Helper: While in a SMARTLIST_FOREACH loop over the list <b>sl</b> indexed
  117. * with the variable <b>var</b>, replace the current element with <b>val</b>.
  118. * Does not deallocate the current value of <b>var</b>.
  119. */
  120. #define SMARTLIST_REPLACE_CURRENT(sl, var, val) \
  121. STMT_BEGIN \
  122. smartlist_set(sl, var ## _sl_idx, val); \
  123. STMT_END
  124. #endif /* !defined(TOR_SMARTLIST_FOREACH_H) */