foreach.h 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. /* Licensed under LGPLv3+ - see LICENSE file for details */
  2. #ifndef CCAN_FOREACH_H
  3. #define CCAN_FOREACH_H
  4. #include "config.h"
  5. #include <stddef.h>
  6. #include <assert.h>
  7. #include <stdbool.h>
  8. #if HAVE_COMPOUND_LITERALS
  9. #if HAVE_FOR_LOOP_DECLARATION
  10. /**
  11. * foreach_int - iterate over a fixed series of integers
  12. * @i: the int-compatible iteration variable
  13. * ...: one or more integer-compatible values
  14. *
  15. * This is a convenient wrapper function for setting a variable to one or
  16. * more explicit values in turn. continue and break work as expected.
  17. *
  18. * Example:
  19. * int i;
  20. * foreach_int(i, 0, -1, 100, 0, -99) {
  21. * printf("i is %i\n", i);
  22. * }
  23. */
  24. #define foreach_int(i, ...) \
  25. for (unsigned _foreach_i = (((i) = ((int[]) { __VA_ARGS__ })[0]), 0); \
  26. _foreach_i < sizeof((int[]) { __VA_ARGS__ })/sizeof(int); \
  27. (i) = ((int[]) { __VA_ARGS__, 0 })[++_foreach_i])
  28. /**
  29. * foreach_ptr - iterate over a non-NULL series of pointers
  30. * @i: the pointer iteration variable
  31. * ...: one or more compatible pointer values
  32. *
  33. * This is a convenient wrapper function for setting a variable to one
  34. * or more explicit values in turn. None of the values can be NULL;
  35. * that is the termination condition (ie. @i will be NULL on
  36. * completion). continue and break work as expected.
  37. *
  38. * Example:
  39. * const char *p;
  40. * foreach_ptr(p, "Hello", "world") {
  41. * printf("p is %s\n", p);
  42. * }
  43. */
  44. #define foreach_ptr(i, ...) \
  45. for (unsigned _foreach_i \
  46. = (((i) = (void *)((FOREACH_TYPEOF(i)[]){ __VA_ARGS__ })[0]), 0); \
  47. (i); \
  48. (i) = (void *)((FOREACH_TYPEOF(i)[]) \
  49. { __VA_ARGS__, NULL})[++_foreach_i], \
  50. _foreach_no_nullval(_foreach_i, i, \
  51. ((const void *[]){ __VA_ARGS__})))
  52. #else /* !HAVE_FOR_LOOP_DECLARATION */
  53. /* GCC in C89 mode still has compound literals, but no for-declarations */
  54. #define foreach_int(i, ...) \
  55. for ((i) = ((int[]){ __VA_ARGS__ })[0], _foreach_iter_init(&(i)); \
  56. _foreach_iter(&(i)) < sizeof((int[]) { __VA_ARGS__ }) \
  57. / sizeof(int); \
  58. (i) = (int[]) { __VA_ARGS__, 0 }[_foreach_iter_inc(&(i))])
  59. #define foreach_ptr(i, ...) \
  60. for ((i) = (void *)((FOREACH_TYPEOF(i)[]){ __VA_ARGS__ })[0], \
  61. _foreach_iter_init(&(i)); \
  62. (i); \
  63. (i) = (void *)((FOREACH_TYPEOF(i)[]){ __VA_ARGS__, NULL }) \
  64. [_foreach_iter_inc(&(i))], \
  65. _foreach_no_nullval(_foreach_iter(&(i)), i, \
  66. ((const void *[]){ __VA_ARGS__})))
  67. void _foreach_iter_init(const void *i);
  68. unsigned int _foreach_iter(const void *i);
  69. unsigned int _foreach_iter_inc(const void *i);
  70. #endif /* !HAVE_FOR_LOOP_DECLARATION */
  71. /* Make sure they don't put NULL values into array! */
  72. #define _foreach_no_nullval(i, p, arr) \
  73. assert((i) >= sizeof(arr)/sizeof(arr[0]) || (p))
  74. #if HAVE_TYPEOF
  75. #define FOREACH_TYPEOF(i) __typeof__(i)
  76. #else
  77. #define FOREACH_TYPEOF(i) const void *
  78. #endif
  79. #else /* !HAVE_COMPOUND_LITERALS */
  80. /* No compound literals, but it's still (just) possible. */
  81. #define foreach_int(i, ...) \
  82. for (i = _foreach_intval_init(&(i), __VA_ARGS__, _foreach_term); \
  83. !_foreach_intval_done(&i); \
  84. i = _foreach_intval_next(&(i), __VA_ARGS__, _foreach_term))
  85. #define foreach_ptr(i, ...) \
  86. for (i = _foreach_ptrval_init(&(i), __VA_ARGS__, NULL); \
  87. (i); \
  88. i = _foreach_ptrval_next(&(i), __VA_ARGS__, NULL))
  89. extern int _foreach_term;
  90. int _foreach_intval_init(const void *i, int val, ...);
  91. bool _foreach_intval_done(const void *i);
  92. int _foreach_intval_next(const void *i, int val, ...);
  93. void *_foreach_ptrval_init(const void *i, const void *val, ...);
  94. void *_foreach_ptrval_next(const void *i, const void *val, ...);
  95. #endif /* !HAVE_COMPOUND_LITERALS */
  96. #endif /* CCAN_FOREACH_H */