|  | // Copyright 2022 The Dawn & Tint Authors | 
|  | // | 
|  | // Redistribution and use in source and binary forms, with or without | 
|  | // modification, are permitted provided that the following conditions are met: | 
|  | // | 
|  | // 1. Redistributions of source code must retain the above copyright notice, this | 
|  | //    list of conditions and the following disclaimer. | 
|  | // | 
|  | // 2. Redistributions in binary form must reproduce the above copyright notice, | 
|  | //    this list of conditions and the following disclaimer in the documentation | 
|  | //    and/or other materials provided with the distribution. | 
|  | // | 
|  | // 3. Neither the name of the copyright holder nor the names of its | 
|  | //    contributors may be used to endorse or promote products derived from | 
|  | //    this software without specific prior written permission. | 
|  | // | 
|  | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | 
|  | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 
|  | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | 
|  | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE | 
|  | // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 
|  | // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | 
|  | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | 
|  | // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | 
|  | // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
|  | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
|  |  | 
|  | #ifndef SRC_TINT_UTILS_MACROS_FOREACH_H_ | 
|  | #define SRC_TINT_UTILS_MACROS_FOREACH_H_ | 
|  |  | 
|  | // Macro magic to perform macro variadic dispatch. | 
|  | // See: | 
|  | // https://renenyffenegger.ch/notes/development/languages/C-C-plus-plus/preprocessor/macros/__VA_ARGS__/count-arguments | 
|  | // Note, this doesn't attempt to use the ##__VA_ARGS__ trick to handle 0 | 
|  |  | 
|  | // Helper macro to force expanding __VA_ARGS__ to satisfy MSVC compiler. | 
|  | #define TINT_MSVC_EXPAND_BUG(X) X | 
|  |  | 
|  | /// TINT_COUNT_ARGUMENTS_NTH_ARG is used by TINT_COUNT_ARGUMENTS to get the number of arguments in a | 
|  | /// variadic macro call. | 
|  | #define TINT_COUNT_ARGUMENTS_NTH_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, \ | 
|  | _15, _16, N, ...)                                            \ | 
|  | N | 
|  |  | 
|  | /// TINT_COUNT_ARGUMENTS evaluates to the number of arguments passed to the macro | 
|  | #define TINT_COUNT_ARGUMENTS(...)                                                                 \ | 
|  | TINT_MSVC_EXPAND_BUG(TINT_COUNT_ARGUMENTS_NTH_ARG(__VA_ARGS__, 16, 15, 14, 13, 12, 11, 10, 9, \ | 
|  | 8, 7, 6, 5, 4, 3, 2, 1, 0)) | 
|  |  | 
|  | // Correctness checks. | 
|  | static_assert(1 == TINT_COUNT_ARGUMENTS(a), "TINT_COUNT_ARGUMENTS broken"); | 
|  | static_assert(2 == TINT_COUNT_ARGUMENTS(a, b), "TINT_COUNT_ARGUMENTS broken"); | 
|  | static_assert(3 == TINT_COUNT_ARGUMENTS(a, b, c), "TINT_COUNT_ARGUMENTS broken"); | 
|  |  | 
|  | /// TINT_FOREACH calls CB with each of the variadic arguments. | 
|  | #define TINT_FOREACH(CB, ...) \ | 
|  | TINT_MSVC_EXPAND_BUG(     \ | 
|  | TINT_CONCAT(TINT_FOREACH_, TINT_COUNT_ARGUMENTS(__VA_ARGS__))(CB, __VA_ARGS__)) | 
|  |  | 
|  | #define TINT_FOREACH_1(CB, _1) CB(_1) | 
|  | #define TINT_FOREACH_2(CB, _1, _2) \ | 
|  | TINT_FOREACH_1(CB, _1)         \ | 
|  | CB(_2) | 
|  | #define TINT_FOREACH_3(CB, _1, _2, _3) \ | 
|  | TINT_FOREACH_2(CB, _1, _2)         \ | 
|  | CB(_3) | 
|  | #define TINT_FOREACH_4(CB, _1, _2, _3, _4) \ | 
|  | TINT_FOREACH_3(CB, _1, _2, _3)         \ | 
|  | CB(_4) | 
|  | #define TINT_FOREACH_5(CB, _1, _2, _3, _4, _5) \ | 
|  | TINT_FOREACH_4(CB, _1, _2, _3, _4)         \ | 
|  | CB(_5) | 
|  | #define TINT_FOREACH_6(CB, _1, _2, _3, _4, _5, _6) \ | 
|  | TINT_FOREACH_5(CB, _1, _2, _3, _4, _5)         \ | 
|  | CB(_6) | 
|  | #define TINT_FOREACH_7(CB, _1, _2, _3, _4, _5, _6, _7) \ | 
|  | TINT_FOREACH_6(CB, _1, _2, _3, _4, _5, _6)         \ | 
|  | CB(_7) | 
|  | #define TINT_FOREACH_8(CB, _1, _2, _3, _4, _5, _6, _7, _8) \ | 
|  | TINT_FOREACH_7(CB, _1, _2, _3, _4, _5, _6, _7)         \ | 
|  | CB(_8) | 
|  | #define TINT_FOREACH_9(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9) \ | 
|  | TINT_FOREACH_8(CB, _1, _2, _3, _4, _5, _6, _7, _8)         \ | 
|  | CB(_9) | 
|  | #define TINT_FOREACH_10(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10) \ | 
|  | TINT_FOREACH_9(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9)           \ | 
|  | CB(_10) | 
|  | #define TINT_FOREACH_11(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11) \ | 
|  | TINT_FOREACH_10(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10)          \ | 
|  | CB(_11) | 
|  | #define TINT_FOREACH_12(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12) \ | 
|  | TINT_FOREACH_11(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11)          \ | 
|  | CB(_12) | 
|  | #define TINT_FOREACH_13(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13) \ | 
|  | TINT_FOREACH_11(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12)          \ | 
|  | CB(_13) | 
|  | #define TINT_FOREACH_14(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14) \ | 
|  | TINT_FOREACH_11(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13)          \ | 
|  | CB(_14) | 
|  | #define TINT_FOREACH_15(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15) \ | 
|  | TINT_FOREACH_11(CB, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14)          \ | 
|  | CB(_15) | 
|  |  | 
|  | #endif  // SRC_TINT_UTILS_MACROS_FOREACH_H_ |