smartlist_foreach.h 4.6 KB

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