// // BKMacros.h // BlocksKit // // Includes code by Michael Ash. . // #import "NSArray+BlocksKit.h" #import "NSSet+BlocksKit.h" #import "NSDictionary+BlocksKit.h" #import "NSIndexSet+BlocksKit.h" #ifndef __BLOCKSKIT_MACROS__ #define __BLOCKSKIT_MACROS__ #define __BK_EACH_WRAPPER(...) (^{ __block CFMutableDictionaryRef BK_eachTable = nil; \ (void)BK_eachTable; \ __typeof__(__VA_ARGS__) BK_retval = __VA_ARGS__; \ if(BK_eachTable) \ CFRelease(BK_eachTable); \ return BK_retval; \ }()) #define __BK_EACH_WRAPPER_VOID(...) (^{ __block CFMutableDictionaryRef BK_eachTable = nil; \ (void)BK_eachTable; \ __VA_ARGS__; \ if(BK_eachTable) \ CFRelease(BK_eachTable); \ }()) #define BK_EACH(collection, ...) __BK_EACH_WRAPPER_VOID([collection bk_each:^(id obj) { __VA_ARGS__ }]) #define BK_MAP(collection, ...) __BK_EACH_WRAPPER([collection bk_map:^id(id obj) { return (__VA_ARGS__); }]) #define BK_SELECT(collection, ...) __BK_EACH_WRAPPER([collection bk_select: ^BOOL (id obj) { return (__VA_ARGS__) != 0; }]) #define BK_REJECT(collection, ...) __BK_EACH_WRAPPER([collection bk_select: ^BOOL (id obj) { return (__VA_ARGS__) == 0; }]) #define BK_MATCH(collection, ...) __BK_EACH_WRAPPER([collection bk_match: ^BOOL (id obj) { return (__VA_ARGS__) != 0; }]) #define BK_REDUCE(collection, initial, ...) __BK_EACH_WRAPPER([collection bk_reduce: (initial) withBlock: ^id (id a, id b) { return (__VA_ARGS__); }]) // BK_APPLY is not wrapped, because we don't guarantee that the order matches the current collection during parallel execution. #define BK_APPLY(collection, ...) [collection bk_apply:^(id obj) { __VA_ARGS__ }] static inline id BKNextHelper(NSArray *array, CFMutableDictionaryRef *eachTablePtr) { if (!*eachTablePtr) { CFDictionaryKeyCallBacks keycb = { 0, kCFTypeDictionaryKeyCallBacks.retain, kCFTypeDictionaryKeyCallBacks.release, kCFTypeDictionaryKeyCallBacks.copyDescription, NULL, NULL }; *eachTablePtr = CFDictionaryCreateMutable(NULL, 0, &keycb, &kCFTypeDictionaryValueCallBacks); } NSEnumerator *enumerator = (__bridge id)CFDictionaryGetValue(*eachTablePtr, (__bridge CFArrayRef)array); if (!enumerator) { enumerator = [array objectEnumerator]; CFDictionarySetValue(*eachTablePtr, (__bridge CFArrayRef)array, (__bridge void *)enumerator); } return [enumerator nextObject]; } #define BK_NEXT(array) BKNextHelper(array, &BK_eachTable) #ifndef EACH #define EACH BK_EACH #endif #ifndef APPLY #define APPLY BK_APPLY #endif #ifndef MAP #define MAP BK_MAP #endif #ifndef SELECT #define SELECT BK_SELECT #endif #ifndef REJECT #define REJECT BK_REJECT #endif #ifndef MATCH #define MATCH BK_MATCH #endif #ifndef REDUCE #define REDUCE BK_REDUCE #endif #ifndef NEXT #define NEXT BK_NEXT #endif #endif