Merge pull request #2647 from dreampiggy/project_weak_strong_macros
Introduce the internal macros and replace the weak-strong dance code with weakify && strongify
This commit is contained in:
commit
6621f6a37d
|
@ -6,5 +6,5 @@
|
|||
// Name of an asset catalog app icon set whose contents will be merged into the `Info.plist`.
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon
|
||||
|
||||
// The compiler to use for C, C++, and Objective-C.
|
||||
GCC_VERSION =
|
||||
// Implicitly include the named header. The path given should either be a project relative path or an absolute path.
|
||||
GCC_PREFIX_HEADER =
|
||||
|
|
|
@ -228,3 +228,6 @@ VERSIONING_SYSTEM = apple-generic
|
|||
|
||||
// Code will load on this and later versions of watchOS. Framework APIs that are unavailable in earlier versions will be weak-linked; your code should check for null function pointers or specific system versions before calling newer APIs.
|
||||
WATCHOS_DEPLOYMENT_TARGET = 2.0
|
||||
|
||||
// Implicitly include the named header. The path given should either be a project relative path or an absolute path.
|
||||
GCC_PREFIX_HEADER = WebImage/SDWebImage-Prefix.pch
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
// Configuration settings file format documentation can be found at:
|
||||
// https://help.apple.com/xcode/#/dev745c5c974
|
||||
|
||||
#include "Module-Debug.xcconfig"
|
||||
#include "Test-Shared.xcconfig"
|
|
@ -0,0 +1,5 @@
|
|||
// Configuration settings file format documentation can be found at:
|
||||
// https://help.apple.com/xcode/#/dev745c5c974
|
||||
|
||||
#include "Module-Release.xcconfig"
|
||||
#include "Test-Shared.xcconfig"
|
|
@ -0,0 +1,7 @@
|
|||
// Configuration settings file format documentation can be found at:
|
||||
// https://help.apple.com/xcode/#/dev745c5c974
|
||||
|
||||
#include "Module-Shared.xcconfig"
|
||||
|
||||
// Implicitly include the named header. The path given should either be a project relative path or an absolute path.
|
||||
GCC_PREFIX_HEADER =
|
|
@ -31,6 +31,7 @@ Pod::Spec.new do |s|
|
|||
core.source_files = 'SDWebImage/*.{h,m}', 'WebImage/SDWebImage.h', 'SDWebImage/Private/*.{h,m}'
|
||||
core.exclude_files = 'SDWebImage/MapKit/*.{h,m}'
|
||||
core.private_header_files = 'SDWebImage/Private/*.h'
|
||||
core.prefix_header_contents = '#import "SDInternalMacros.h"'
|
||||
end
|
||||
|
||||
s.subspec 'MapKit' do |mk|
|
||||
|
|
|
@ -115,6 +115,12 @@
|
|||
329A185B1FFF5DFD008C9A2F /* UIImage+Metadata.h in Headers */ = {isa = PBXBuildFile; fileRef = 329A18571FFF5DFD008C9A2F /* UIImage+Metadata.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
329A185F1FFF5DFD008C9A2F /* UIImage+Metadata.m in Sources */ = {isa = PBXBuildFile; fileRef = 329A18581FFF5DFD008C9A2F /* UIImage+Metadata.m */; };
|
||||
329A18611FFF5DFD008C9A2F /* UIImage+Metadata.m in Sources */ = {isa = PBXBuildFile; fileRef = 329A18581FFF5DFD008C9A2F /* UIImage+Metadata.m */; };
|
||||
329F1236223FAA3B00B309FD /* SDmetamacros.h in Headers */ = {isa = PBXBuildFile; fileRef = 329F1235223FAA3B00B309FD /* SDmetamacros.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
||||
329F1237223FAA3B00B309FD /* SDmetamacros.h in Headers */ = {isa = PBXBuildFile; fileRef = 329F1235223FAA3B00B309FD /* SDmetamacros.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
||||
329F1240223FAD3400B309FD /* SDInternalMacros.m in Sources */ = {isa = PBXBuildFile; fileRef = 329F123E223FAD3400B309FD /* SDInternalMacros.m */; };
|
||||
329F1241223FAD3400B309FD /* SDInternalMacros.m in Sources */ = {isa = PBXBuildFile; fileRef = 329F123E223FAD3400B309FD /* SDInternalMacros.m */; };
|
||||
329F1242223FAD3400B309FD /* SDInternalMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = 329F123F223FAD3400B309FD /* SDInternalMacros.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
||||
329F1243223FAD3400B309FD /* SDInternalMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = 329F123F223FAD3400B309FD /* SDInternalMacros.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
||||
32B5CC60222F89C2005EB74E /* SDAsyncBlockOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 32B5CC5E222F89C2005EB74E /* SDAsyncBlockOperation.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
||||
32B5CC61222F89C2005EB74E /* SDAsyncBlockOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 32B5CC5F222F89C2005EB74E /* SDAsyncBlockOperation.m */; };
|
||||
32B5CC62222F89F6005EB74E /* SDAsyncBlockOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 32B5CC5E222F89C2005EB74E /* SDAsyncBlockOperation.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
||||
|
@ -309,6 +315,9 @@
|
|||
3290FA031FA478AF0047D20C /* SDImageFrame.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDImageFrame.m; sourceTree = "<group>"; };
|
||||
329A18571FFF5DFD008C9A2F /* UIImage+Metadata.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage+Metadata.h"; sourceTree = "<group>"; };
|
||||
329A18581FFF5DFD008C9A2F /* UIImage+Metadata.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+Metadata.m"; sourceTree = "<group>"; };
|
||||
329F1235223FAA3B00B309FD /* SDmetamacros.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDmetamacros.h; sourceTree = "<group>"; };
|
||||
329F123E223FAD3400B309FD /* SDInternalMacros.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDInternalMacros.m; sourceTree = "<group>"; };
|
||||
329F123F223FAD3400B309FD /* SDInternalMacros.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDInternalMacros.h; sourceTree = "<group>"; };
|
||||
32B5CC5E222F89C2005EB74E /* SDAsyncBlockOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDAsyncBlockOperation.h; sourceTree = "<group>"; };
|
||||
32B5CC5F222F89C2005EB74E /* SDAsyncBlockOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDAsyncBlockOperation.m; sourceTree = "<group>"; };
|
||||
32B9B535206ED4230026769D /* SDWebImageDownloaderConfig.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDWebImageDownloaderConfig.h; sourceTree = "<group>"; };
|
||||
|
@ -497,6 +506,9 @@
|
|||
325C461F2233A02E004CAE11 /* UIColor+HexString.m */,
|
||||
325C46242233A0A8004CAE11 /* NSBezierPath+RoundedCorners.h */,
|
||||
325C46252233A0A8004CAE11 /* NSBezierPath+RoundedCorners.m */,
|
||||
329F123F223FAD3400B309FD /* SDInternalMacros.h */,
|
||||
329F123E223FAD3400B309FD /* SDInternalMacros.m */,
|
||||
329F1235223FAA3B00B309FD /* SDmetamacros.h */,
|
||||
);
|
||||
path = Private;
|
||||
sourceTree = "<group>";
|
||||
|
@ -715,6 +727,7 @@
|
|||
80B6DF842142B44600BCB334 /* NSButton+WebCache.h in Headers */,
|
||||
43A918661D8308FE00B3925F /* SDImageCacheConfig.h in Headers */,
|
||||
3290FA061FA478AF0047D20C /* SDImageFrame.h in Headers */,
|
||||
329F1237223FAA3B00B309FD /* SDmetamacros.h in Headers */,
|
||||
324DF4B6200A14DC008A84CC /* SDWebImageDefine.h in Headers */,
|
||||
807A122A1F89636300EC2A9B /* SDImageCodersManager.h in Headers */,
|
||||
4A2CAE211AB4BB7000B6BC39 /* SDWebImageManager.h in Headers */,
|
||||
|
@ -749,6 +762,7 @@
|
|||
325C4615223399F7004CAE11 /* SDImageGIFCoderInternal.h in Headers */,
|
||||
32F7C0862030719600873181 /* UIImage+Transform.h in Headers */,
|
||||
321E60C01F38E91700405457 /* UIImage+ForceDecode.h in Headers */,
|
||||
329F1243223FAD3400B309FD /* SDInternalMacros.h in Headers */,
|
||||
80B6DF7F2142B43300BCB334 /* NSImage+Compatibility.h in Headers */,
|
||||
32C0FDE32013426C001B8F2D /* SDWebImageIndicator.h in Headers */,
|
||||
32F7C0712030114C00873181 /* SDImageTransformer.h in Headers */,
|
||||
|
@ -780,6 +794,7 @@
|
|||
80B6DF852142B44700BCB334 /* NSButton+WebCache.h in Headers */,
|
||||
807A12281F89636300EC2A9B /* SDImageCodersManager.h in Headers */,
|
||||
32B9B537206ED4230026769D /* SDWebImageDownloaderConfig.h in Headers */,
|
||||
329F1236223FAA3B00B309FD /* SDmetamacros.h in Headers */,
|
||||
32484775201775F600AF9E5A /* SDAnimatedImage.h in Headers */,
|
||||
321E60941F38E8ED00405457 /* SDImageIOCoder.h in Headers */,
|
||||
329A18591FFF5DFD008C9A2F /* UIImage+Metadata.h in Headers */,
|
||||
|
@ -814,6 +829,7 @@
|
|||
325C4614223399F7004CAE11 /* SDImageGIFCoderInternal.h in Headers */,
|
||||
321E60861F38E8C800405457 /* SDImageCoder.h in Headers */,
|
||||
32484763201775F600AF9E5A /* SDAnimatedImageView+WebCache.h in Headers */,
|
||||
329F1242223FAD3400B309FD /* SDInternalMacros.h in Headers */,
|
||||
80B6DF7E2142B43300BCB334 /* NSImage+Compatibility.h in Headers */,
|
||||
32D1221E2080B2EB003685A3 /* SDImageCacheDefine.h in Headers */,
|
||||
AB615303192DA24600A2D8E9 /* UIView+WebCacheOperation.h in Headers */,
|
||||
|
@ -971,6 +987,7 @@
|
|||
4A2CAE2E1AB4BB7500B6BC39 /* UIImage+GIF.m in Sources */,
|
||||
80B6DF822142B44400BCB334 /* NSButton+WebCache.m in Sources */,
|
||||
32D3CDCF21DDE87300C4DB49 /* UIImage+MemoryCacheCost.m in Sources */,
|
||||
329F1241223FAD3400B309FD /* SDInternalMacros.m in Sources */,
|
||||
320CAE1D2086F50500CFFC80 /* SDWebImageError.m in Sources */,
|
||||
32CF1C0F1FA496B000004BD1 /* SDImageCoderHelper.m in Sources */,
|
||||
328BB6D52082581100760D6C /* SDMemoryCache.m in Sources */,
|
||||
|
@ -1032,6 +1049,7 @@
|
|||
53761309155AD0D5005750A4 /* SDImageCache.m in Sources */,
|
||||
80B6DF832142B44500BCB334 /* NSButton+WebCache.m in Sources */,
|
||||
32D3CDCE21DDE87300C4DB49 /* UIImage+MemoryCacheCost.m in Sources */,
|
||||
329F1240223FAD3400B309FD /* SDInternalMacros.m in Sources */,
|
||||
320CAE1B2086F50500CFFC80 /* SDWebImageError.m in Sources */,
|
||||
32CF1C0D1FA496B000004BD1 /* SDImageCoderHelper.m in Sources */,
|
||||
328BB6D32082581100760D6C /* SDMemoryCache.m in Sources */,
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* This file is part of the SDWebImage package.
|
||||
* (c) Olivier Poitrey <rs@dailymotion.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "SDmetamacros.h"
|
||||
|
||||
#ifndef SD_LOCK
|
||||
#define SD_LOCK(lock) dispatch_semaphore_wait(lock, DISPATCH_TIME_FOREVER);
|
||||
#endif
|
||||
|
||||
#ifndef SD_UNLOCK
|
||||
#define SD_UNLOCK(lock) dispatch_semaphore_signal(lock);
|
||||
#endif
|
||||
|
||||
#ifndef weakify
|
||||
#define weakify(...) \
|
||||
sd_keywordify \
|
||||
metamacro_foreach_cxt(sd_weakify_,, __weak, __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#ifndef strongify
|
||||
#define strongify(...) \
|
||||
sd_keywordify \
|
||||
_Pragma("clang diagnostic push") \
|
||||
_Pragma("clang diagnostic ignored \"-Wshadow\"") \
|
||||
metamacro_foreach(sd_strongify_,, __VA_ARGS__) \
|
||||
_Pragma("clang diagnostic pop")
|
||||
#endif
|
||||
|
||||
#define sd_weakify_(INDEX, CONTEXT, VAR) \
|
||||
CONTEXT __typeof__(VAR) metamacro_concat(VAR, _weak_) = (VAR);
|
||||
|
||||
#define sd_strongify_(INDEX, VAR) \
|
||||
__strong __typeof__(VAR) VAR = metamacro_concat(VAR, _weak_);
|
||||
|
||||
#if DEBUG
|
||||
#define sd_keywordify autoreleasepool {}
|
||||
#else
|
||||
#define sd_keywordify try {} @catch (...) {}
|
||||
#endif
|
||||
|
||||
#ifndef onExit
|
||||
#define onExit \
|
||||
sd_keywordify \
|
||||
__strong sd_cleanupBlock_t metamacro_concat(sd_exitBlock_, __LINE__) __attribute__((cleanup(sd_executeCleanupBlock), unused)) = ^
|
||||
#endif
|
||||
|
||||
typedef void (^sd_cleanupBlock_t)(void);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
void sd_executeCleanupBlock (__strong sd_cleanupBlock_t *block);
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,13 @@
|
|||
/*
|
||||
* This file is part of the SDWebImage package.
|
||||
* (c) Olivier Poitrey <rs@dailymotion.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
#import "SDInternalMacros.h"
|
||||
|
||||
void sd_executeCleanupBlock (__strong sd_cleanupBlock_t *block) {
|
||||
(*block)();
|
||||
}
|
|
@ -0,0 +1,667 @@
|
|||
/**
|
||||
* Macros for metaprogramming
|
||||
* ExtendedC
|
||||
*
|
||||
* Copyright (C) 2012 Justin Spahr-Summers
|
||||
* Released under the MIT license
|
||||
*/
|
||||
|
||||
#ifndef EXTC_METAMACROS_H
|
||||
#define EXTC_METAMACROS_H
|
||||
|
||||
|
||||
/**
|
||||
* Executes one or more expressions (which may have a void type, such as a call
|
||||
* to a function that returns no value) and always returns true.
|
||||
*/
|
||||
#define metamacro_exprify(...) \
|
||||
((__VA_ARGS__), true)
|
||||
|
||||
/**
|
||||
* Returns a string representation of VALUE after full macro expansion.
|
||||
*/
|
||||
#define metamacro_stringify(VALUE) \
|
||||
metamacro_stringify_(VALUE)
|
||||
|
||||
/**
|
||||
* Returns A and B concatenated after full macro expansion.
|
||||
*/
|
||||
#define metamacro_concat(A, B) \
|
||||
metamacro_concat_(A, B)
|
||||
|
||||
/**
|
||||
* Returns the Nth variadic argument (starting from zero). At least
|
||||
* N + 1 variadic arguments must be given. N must be between zero and twenty,
|
||||
* inclusive.
|
||||
*/
|
||||
#define metamacro_at(N, ...) \
|
||||
metamacro_concat(metamacro_at, N)(__VA_ARGS__)
|
||||
|
||||
/**
|
||||
* Returns the number of arguments (up to twenty) provided to the macro. At
|
||||
* least one argument must be provided.
|
||||
*
|
||||
* Inspired by P99: http://p99.gforge.inria.fr
|
||||
*/
|
||||
#define metamacro_argcount(...) \
|
||||
metamacro_at(20, __VA_ARGS__, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
|
||||
|
||||
/**
|
||||
* Identical to #metamacro_foreach_cxt, except that no CONTEXT argument is
|
||||
* given. Only the index and current argument will thus be passed to MACRO.
|
||||
*/
|
||||
#define metamacro_foreach(MACRO, SEP, ...) \
|
||||
metamacro_foreach_cxt(metamacro_foreach_iter, SEP, MACRO, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* For each consecutive variadic argument (up to twenty), MACRO is passed the
|
||||
* zero-based index of the current argument, CONTEXT, and then the argument
|
||||
* itself. The results of adjoining invocations of MACRO are then separated by
|
||||
* SEP.
|
||||
*
|
||||
* Inspired by P99: http://p99.gforge.inria.fr
|
||||
*/
|
||||
#define metamacro_foreach_cxt(MACRO, SEP, CONTEXT, ...) \
|
||||
metamacro_concat(metamacro_foreach_cxt, metamacro_argcount(__VA_ARGS__))(MACRO, SEP, CONTEXT, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* Identical to #metamacro_foreach_cxt. This can be used when the former would
|
||||
* fail due to recursive macro expansion.
|
||||
*/
|
||||
#define metamacro_foreach_cxt_recursive(MACRO, SEP, CONTEXT, ...) \
|
||||
metamacro_concat(metamacro_foreach_cxt_recursive, metamacro_argcount(__VA_ARGS__))(MACRO, SEP, CONTEXT, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* In consecutive order, appends each variadic argument (up to twenty) onto
|
||||
* BASE. The resulting concatenations are then separated by SEP.
|
||||
*
|
||||
* This is primarily useful to manipulate a list of macro invocations into instead
|
||||
* invoking a different, possibly related macro.
|
||||
*/
|
||||
#define metamacro_foreach_concat(BASE, SEP, ...) \
|
||||
metamacro_foreach_cxt(metamacro_foreach_concat_iter, SEP, BASE, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* Iterates COUNT times, each time invoking MACRO with the current index
|
||||
* (starting at zero) and CONTEXT. The results of adjoining invocations of MACRO
|
||||
* are then separated by SEP.
|
||||
*
|
||||
* COUNT must be an integer between zero and twenty, inclusive.
|
||||
*/
|
||||
#define metamacro_for_cxt(COUNT, MACRO, SEP, CONTEXT) \
|
||||
metamacro_concat(metamacro_for_cxt, COUNT)(MACRO, SEP, CONTEXT)
|
||||
|
||||
/**
|
||||
* Returns the first argument given. At least one argument must be provided.
|
||||
*
|
||||
* This is useful when implementing a variadic macro, where you may have only
|
||||
* one variadic argument, but no way to retrieve it (for example, because \c ...
|
||||
* always needs to match at least one argument).
|
||||
*
|
||||
* @code
|
||||
|
||||
#define varmacro(...) \
|
||||
metamacro_head(__VA_ARGS__)
|
||||
|
||||
* @endcode
|
||||
*/
|
||||
#define metamacro_head(...) \
|
||||
metamacro_head_(__VA_ARGS__, 0)
|
||||
|
||||
/**
|
||||
* Returns every argument except the first. At least two arguments must be
|
||||
* provided.
|
||||
*/
|
||||
#define metamacro_tail(...) \
|
||||
metamacro_tail_(__VA_ARGS__)
|
||||
|
||||
/**
|
||||
* Returns the first N (up to twenty) variadic arguments as a new argument list.
|
||||
* At least N variadic arguments must be provided.
|
||||
*/
|
||||
#define metamacro_take(N, ...) \
|
||||
metamacro_concat(metamacro_take, N)(__VA_ARGS__)
|
||||
|
||||
/**
|
||||
* Removes the first N (up to twenty) variadic arguments from the given argument
|
||||
* list. At least N variadic arguments must be provided.
|
||||
*/
|
||||
#define metamacro_drop(N, ...) \
|
||||
metamacro_concat(metamacro_drop, N)(__VA_ARGS__)
|
||||
|
||||
/**
|
||||
* Decrements VAL, which must be a number between zero and twenty, inclusive.
|
||||
*
|
||||
* This is primarily useful when dealing with indexes and counts in
|
||||
* metaprogramming.
|
||||
*/
|
||||
#define metamacro_dec(VAL) \
|
||||
metamacro_at(VAL, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19)
|
||||
|
||||
/**
|
||||
* Increments VAL, which must be a number between zero and twenty, inclusive.
|
||||
*
|
||||
* This is primarily useful when dealing with indexes and counts in
|
||||
* metaprogramming.
|
||||
*/
|
||||
#define metamacro_inc(VAL) \
|
||||
metamacro_at(VAL, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21)
|
||||
|
||||
/**
|
||||
* If A is equal to B, the next argument list is expanded; otherwise, the
|
||||
* argument list after that is expanded. A and B must be numbers between zero
|
||||
* and twenty, inclusive. Additionally, B must be greater than or equal to A.
|
||||
*
|
||||
* @code
|
||||
|
||||
// expands to true
|
||||
metamacro_if_eq(0, 0)(true)(false)
|
||||
|
||||
// expands to false
|
||||
metamacro_if_eq(0, 1)(true)(false)
|
||||
|
||||
* @endcode
|
||||
*
|
||||
* This is primarily useful when dealing with indexes and counts in
|
||||
* metaprogramming.
|
||||
*/
|
||||
#define metamacro_if_eq(A, B) \
|
||||
metamacro_concat(metamacro_if_eq, A)(B)
|
||||
|
||||
/**
|
||||
* Identical to #metamacro_if_eq. This can be used when the former would fail
|
||||
* due to recursive macro expansion.
|
||||
*/
|
||||
#define metamacro_if_eq_recursive(A, B) \
|
||||
metamacro_concat(metamacro_if_eq_recursive, A)(B)
|
||||
|
||||
/**
|
||||
* Returns 1 if N is an even number, or 0 otherwise. N must be between zero and
|
||||
* twenty, inclusive.
|
||||
*
|
||||
* For the purposes of this test, zero is considered even.
|
||||
*/
|
||||
#define metamacro_is_even(N) \
|
||||
metamacro_at(N, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1)
|
||||
|
||||
/**
|
||||
* Returns the logical NOT of B, which must be the number zero or one.
|
||||
*/
|
||||
#define metamacro_not(B) \
|
||||
metamacro_at(B, 1, 0)
|
||||
|
||||
// IMPLEMENTATION DETAILS FOLLOW!
|
||||
// Do not write code that depends on anything below this line.
|
||||
#define metamacro_stringify_(VALUE) # VALUE
|
||||
#define metamacro_concat_(A, B) A ## B
|
||||
#define metamacro_foreach_iter(INDEX, MACRO, ARG) MACRO(INDEX, ARG)
|
||||
#define metamacro_head_(FIRST, ...) FIRST
|
||||
#define metamacro_tail_(FIRST, ...) __VA_ARGS__
|
||||
#define metamacro_consume_(...)
|
||||
#define metamacro_expand_(...) __VA_ARGS__
|
||||
|
||||
// implemented from scratch so that metamacro_concat() doesn't end up nesting
|
||||
#define metamacro_foreach_concat_iter(INDEX, BASE, ARG) metamacro_foreach_concat_iter_(BASE, ARG)
|
||||
#define metamacro_foreach_concat_iter_(BASE, ARG) BASE ## ARG
|
||||
|
||||
// metamacro_at expansions
|
||||
#define metamacro_at0(...) metamacro_head(__VA_ARGS__)
|
||||
#define metamacro_at1(_0, ...) metamacro_head(__VA_ARGS__)
|
||||
#define metamacro_at2(_0, _1, ...) metamacro_head(__VA_ARGS__)
|
||||
#define metamacro_at3(_0, _1, _2, ...) metamacro_head(__VA_ARGS__)
|
||||
#define metamacro_at4(_0, _1, _2, _3, ...) metamacro_head(__VA_ARGS__)
|
||||
#define metamacro_at5(_0, _1, _2, _3, _4, ...) metamacro_head(__VA_ARGS__)
|
||||
#define metamacro_at6(_0, _1, _2, _3, _4, _5, ...) metamacro_head(__VA_ARGS__)
|
||||
#define metamacro_at7(_0, _1, _2, _3, _4, _5, _6, ...) metamacro_head(__VA_ARGS__)
|
||||
#define metamacro_at8(_0, _1, _2, _3, _4, _5, _6, _7, ...) metamacro_head(__VA_ARGS__)
|
||||
#define metamacro_at9(_0, _1, _2, _3, _4, _5, _6, _7, _8, ...) metamacro_head(__VA_ARGS__)
|
||||
#define metamacro_at10(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, ...) metamacro_head(__VA_ARGS__)
|
||||
#define metamacro_at11(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, ...) metamacro_head(__VA_ARGS__)
|
||||
#define metamacro_at12(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, ...) metamacro_head(__VA_ARGS__)
|
||||
#define metamacro_at13(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, ...) metamacro_head(__VA_ARGS__)
|
||||
#define metamacro_at14(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, ...) metamacro_head(__VA_ARGS__)
|
||||
#define metamacro_at15(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, ...) metamacro_head(__VA_ARGS__)
|
||||
#define metamacro_at16(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, ...) metamacro_head(__VA_ARGS__)
|
||||
#define metamacro_at17(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, ...) metamacro_head(__VA_ARGS__)
|
||||
#define metamacro_at18(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, ...) metamacro_head(__VA_ARGS__)
|
||||
#define metamacro_at19(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, ...) metamacro_head(__VA_ARGS__)
|
||||
#define metamacro_at20(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, ...) metamacro_head(__VA_ARGS__)
|
||||
|
||||
// metamacro_foreach_cxt expansions
|
||||
#define metamacro_foreach_cxt0(MACRO, SEP, CONTEXT)
|
||||
#define metamacro_foreach_cxt1(MACRO, SEP, CONTEXT, _0) MACRO(0, CONTEXT, _0)
|
||||
|
||||
#define metamacro_foreach_cxt2(MACRO, SEP, CONTEXT, _0, _1) \
|
||||
metamacro_foreach_cxt1(MACRO, SEP, CONTEXT, _0) \
|
||||
SEP \
|
||||
MACRO(1, CONTEXT, _1)
|
||||
|
||||
#define metamacro_foreach_cxt3(MACRO, SEP, CONTEXT, _0, _1, _2) \
|
||||
metamacro_foreach_cxt2(MACRO, SEP, CONTEXT, _0, _1) \
|
||||
SEP \
|
||||
MACRO(2, CONTEXT, _2)
|
||||
|
||||
#define metamacro_foreach_cxt4(MACRO, SEP, CONTEXT, _0, _1, _2, _3) \
|
||||
metamacro_foreach_cxt3(MACRO, SEP, CONTEXT, _0, _1, _2) \
|
||||
SEP \
|
||||
MACRO(3, CONTEXT, _3)
|
||||
|
||||
#define metamacro_foreach_cxt5(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4) \
|
||||
metamacro_foreach_cxt4(MACRO, SEP, CONTEXT, _0, _1, _2, _3) \
|
||||
SEP \
|
||||
MACRO(4, CONTEXT, _4)
|
||||
|
||||
#define metamacro_foreach_cxt6(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5) \
|
||||
metamacro_foreach_cxt5(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4) \
|
||||
SEP \
|
||||
MACRO(5, CONTEXT, _5)
|
||||
|
||||
#define metamacro_foreach_cxt7(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6) \
|
||||
metamacro_foreach_cxt6(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5) \
|
||||
SEP \
|
||||
MACRO(6, CONTEXT, _6)
|
||||
|
||||
#define metamacro_foreach_cxt8(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7) \
|
||||
metamacro_foreach_cxt7(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6) \
|
||||
SEP \
|
||||
MACRO(7, CONTEXT, _7)
|
||||
|
||||
#define metamacro_foreach_cxt9(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8) \
|
||||
metamacro_foreach_cxt8(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7) \
|
||||
SEP \
|
||||
MACRO(8, CONTEXT, _8)
|
||||
|
||||
#define metamacro_foreach_cxt10(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9) \
|
||||
metamacro_foreach_cxt9(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8) \
|
||||
SEP \
|
||||
MACRO(9, CONTEXT, _9)
|
||||
|
||||
#define metamacro_foreach_cxt11(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10) \
|
||||
metamacro_foreach_cxt10(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9) \
|
||||
SEP \
|
||||
MACRO(10, CONTEXT, _10)
|
||||
|
||||
#define metamacro_foreach_cxt12(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11) \
|
||||
metamacro_foreach_cxt11(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10) \
|
||||
SEP \
|
||||
MACRO(11, CONTEXT, _11)
|
||||
|
||||
#define metamacro_foreach_cxt13(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12) \
|
||||
metamacro_foreach_cxt12(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11) \
|
||||
SEP \
|
||||
MACRO(12, CONTEXT, _12)
|
||||
|
||||
#define metamacro_foreach_cxt14(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13) \
|
||||
metamacro_foreach_cxt13(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12) \
|
||||
SEP \
|
||||
MACRO(13, CONTEXT, _13)
|
||||
|
||||
#define metamacro_foreach_cxt15(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14) \
|
||||
metamacro_foreach_cxt14(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13) \
|
||||
SEP \
|
||||
MACRO(14, CONTEXT, _14)
|
||||
|
||||
#define metamacro_foreach_cxt16(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15) \
|
||||
metamacro_foreach_cxt15(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14) \
|
||||
SEP \
|
||||
MACRO(15, CONTEXT, _15)
|
||||
|
||||
#define metamacro_foreach_cxt17(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16) \
|
||||
metamacro_foreach_cxt16(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15) \
|
||||
SEP \
|
||||
MACRO(16, CONTEXT, _16)
|
||||
|
||||
#define metamacro_foreach_cxt18(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17) \
|
||||
metamacro_foreach_cxt17(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16) \
|
||||
SEP \
|
||||
MACRO(17, CONTEXT, _17)
|
||||
|
||||
#define metamacro_foreach_cxt19(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18) \
|
||||
metamacro_foreach_cxt18(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17) \
|
||||
SEP \
|
||||
MACRO(18, CONTEXT, _18)
|
||||
|
||||
#define metamacro_foreach_cxt20(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19) \
|
||||
metamacro_foreach_cxt19(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18) \
|
||||
SEP \
|
||||
MACRO(19, CONTEXT, _19)
|
||||
|
||||
// metamacro_foreach_cxt_recursive expansions
|
||||
#define metamacro_foreach_cxt_recursive0(MACRO, SEP, CONTEXT)
|
||||
#define metamacro_foreach_cxt_recursive1(MACRO, SEP, CONTEXT, _0) MACRO(0, CONTEXT, _0)
|
||||
|
||||
#define metamacro_foreach_cxt_recursive2(MACRO, SEP, CONTEXT, _0, _1) \
|
||||
metamacro_foreach_cxt_recursive1(MACRO, SEP, CONTEXT, _0) \
|
||||
SEP \
|
||||
MACRO(1, CONTEXT, _1)
|
||||
|
||||
#define metamacro_foreach_cxt_recursive3(MACRO, SEP, CONTEXT, _0, _1, _2) \
|
||||
metamacro_foreach_cxt_recursive2(MACRO, SEP, CONTEXT, _0, _1) \
|
||||
SEP \
|
||||
MACRO(2, CONTEXT, _2)
|
||||
|
||||
#define metamacro_foreach_cxt_recursive4(MACRO, SEP, CONTEXT, _0, _1, _2, _3) \
|
||||
metamacro_foreach_cxt_recursive3(MACRO, SEP, CONTEXT, _0, _1, _2) \
|
||||
SEP \
|
||||
MACRO(3, CONTEXT, _3)
|
||||
|
||||
#define metamacro_foreach_cxt_recursive5(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4) \
|
||||
metamacro_foreach_cxt_recursive4(MACRO, SEP, CONTEXT, _0, _1, _2, _3) \
|
||||
SEP \
|
||||
MACRO(4, CONTEXT, _4)
|
||||
|
||||
#define metamacro_foreach_cxt_recursive6(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5) \
|
||||
metamacro_foreach_cxt_recursive5(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4) \
|
||||
SEP \
|
||||
MACRO(5, CONTEXT, _5)
|
||||
|
||||
#define metamacro_foreach_cxt_recursive7(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6) \
|
||||
metamacro_foreach_cxt_recursive6(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5) \
|
||||
SEP \
|
||||
MACRO(6, CONTEXT, _6)
|
||||
|
||||
#define metamacro_foreach_cxt_recursive8(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7) \
|
||||
metamacro_foreach_cxt_recursive7(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6) \
|
||||
SEP \
|
||||
MACRO(7, CONTEXT, _7)
|
||||
|
||||
#define metamacro_foreach_cxt_recursive9(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8) \
|
||||
metamacro_foreach_cxt_recursive8(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7) \
|
||||
SEP \
|
||||
MACRO(8, CONTEXT, _8)
|
||||
|
||||
#define metamacro_foreach_cxt_recursive10(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9) \
|
||||
metamacro_foreach_cxt_recursive9(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8) \
|
||||
SEP \
|
||||
MACRO(9, CONTEXT, _9)
|
||||
|
||||
#define metamacro_foreach_cxt_recursive11(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10) \
|
||||
metamacro_foreach_cxt_recursive10(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9) \
|
||||
SEP \
|
||||
MACRO(10, CONTEXT, _10)
|
||||
|
||||
#define metamacro_foreach_cxt_recursive12(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11) \
|
||||
metamacro_foreach_cxt_recursive11(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10) \
|
||||
SEP \
|
||||
MACRO(11, CONTEXT, _11)
|
||||
|
||||
#define metamacro_foreach_cxt_recursive13(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12) \
|
||||
metamacro_foreach_cxt_recursive12(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11) \
|
||||
SEP \
|
||||
MACRO(12, CONTEXT, _12)
|
||||
|
||||
#define metamacro_foreach_cxt_recursive14(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13) \
|
||||
metamacro_foreach_cxt_recursive13(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12) \
|
||||
SEP \
|
||||
MACRO(13, CONTEXT, _13)
|
||||
|
||||
#define metamacro_foreach_cxt_recursive15(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14) \
|
||||
metamacro_foreach_cxt_recursive14(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13) \
|
||||
SEP \
|
||||
MACRO(14, CONTEXT, _14)
|
||||
|
||||
#define metamacro_foreach_cxt_recursive16(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15) \
|
||||
metamacro_foreach_cxt_recursive15(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14) \
|
||||
SEP \
|
||||
MACRO(15, CONTEXT, _15)
|
||||
|
||||
#define metamacro_foreach_cxt_recursive17(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16) \
|
||||
metamacro_foreach_cxt_recursive16(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15) \
|
||||
SEP \
|
||||
MACRO(16, CONTEXT, _16)
|
||||
|
||||
#define metamacro_foreach_cxt_recursive18(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17) \
|
||||
metamacro_foreach_cxt_recursive17(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16) \
|
||||
SEP \
|
||||
MACRO(17, CONTEXT, _17)
|
||||
|
||||
#define metamacro_foreach_cxt_recursive19(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18) \
|
||||
metamacro_foreach_cxt_recursive18(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17) \
|
||||
SEP \
|
||||
MACRO(18, CONTEXT, _18)
|
||||
|
||||
#define metamacro_foreach_cxt_recursive20(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19) \
|
||||
metamacro_foreach_cxt_recursive19(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18) \
|
||||
SEP \
|
||||
MACRO(19, CONTEXT, _19)
|
||||
|
||||
// metamacro_for_cxt expansions
|
||||
#define metamacro_for_cxt0(MACRO, SEP, CONTEXT)
|
||||
#define metamacro_for_cxt1(MACRO, SEP, CONTEXT) MACRO(0, CONTEXT)
|
||||
|
||||
#define metamacro_for_cxt2(MACRO, SEP, CONTEXT) \
|
||||
metamacro_for_cxt1(MACRO, SEP, CONTEXT) \
|
||||
SEP \
|
||||
MACRO(1, CONTEXT)
|
||||
|
||||
#define metamacro_for_cxt3(MACRO, SEP, CONTEXT) \
|
||||
metamacro_for_cxt2(MACRO, SEP, CONTEXT) \
|
||||
SEP \
|
||||
MACRO(2, CONTEXT)
|
||||
|
||||
#define metamacro_for_cxt4(MACRO, SEP, CONTEXT) \
|
||||
metamacro_for_cxt3(MACRO, SEP, CONTEXT) \
|
||||
SEP \
|
||||
MACRO(3, CONTEXT)
|
||||
|
||||
#define metamacro_for_cxt5(MACRO, SEP, CONTEXT) \
|
||||
metamacro_for_cxt4(MACRO, SEP, CONTEXT) \
|
||||
SEP \
|
||||
MACRO(4, CONTEXT)
|
||||
|
||||
#define metamacro_for_cxt6(MACRO, SEP, CONTEXT) \
|
||||
metamacro_for_cxt5(MACRO, SEP, CONTEXT) \
|
||||
SEP \
|
||||
MACRO(5, CONTEXT)
|
||||
|
||||
#define metamacro_for_cxt7(MACRO, SEP, CONTEXT) \
|
||||
metamacro_for_cxt6(MACRO, SEP, CONTEXT) \
|
||||
SEP \
|
||||
MACRO(6, CONTEXT)
|
||||
|
||||
#define metamacro_for_cxt8(MACRO, SEP, CONTEXT) \
|
||||
metamacro_for_cxt7(MACRO, SEP, CONTEXT) \
|
||||
SEP \
|
||||
MACRO(7, CONTEXT)
|
||||
|
||||
#define metamacro_for_cxt9(MACRO, SEP, CONTEXT) \
|
||||
metamacro_for_cxt8(MACRO, SEP, CONTEXT) \
|
||||
SEP \
|
||||
MACRO(8, CONTEXT)
|
||||
|
||||
#define metamacro_for_cxt10(MACRO, SEP, CONTEXT) \
|
||||
metamacro_for_cxt9(MACRO, SEP, CONTEXT) \
|
||||
SEP \
|
||||
MACRO(9, CONTEXT)
|
||||
|
||||
#define metamacro_for_cxt11(MACRO, SEP, CONTEXT) \
|
||||
metamacro_for_cxt10(MACRO, SEP, CONTEXT) \
|
||||
SEP \
|
||||
MACRO(10, CONTEXT)
|
||||
|
||||
#define metamacro_for_cxt12(MACRO, SEP, CONTEXT) \
|
||||
metamacro_for_cxt11(MACRO, SEP, CONTEXT) \
|
||||
SEP \
|
||||
MACRO(11, CONTEXT)
|
||||
|
||||
#define metamacro_for_cxt13(MACRO, SEP, CONTEXT) \
|
||||
metamacro_for_cxt12(MACRO, SEP, CONTEXT) \
|
||||
SEP \
|
||||
MACRO(12, CONTEXT)
|
||||
|
||||
#define metamacro_for_cxt14(MACRO, SEP, CONTEXT) \
|
||||
metamacro_for_cxt13(MACRO, SEP, CONTEXT) \
|
||||
SEP \
|
||||
MACRO(13, CONTEXT)
|
||||
|
||||
#define metamacro_for_cxt15(MACRO, SEP, CONTEXT) \
|
||||
metamacro_for_cxt14(MACRO, SEP, CONTEXT) \
|
||||
SEP \
|
||||
MACRO(14, CONTEXT)
|
||||
|
||||
#define metamacro_for_cxt16(MACRO, SEP, CONTEXT) \
|
||||
metamacro_for_cxt15(MACRO, SEP, CONTEXT) \
|
||||
SEP \
|
||||
MACRO(15, CONTEXT)
|
||||
|
||||
#define metamacro_for_cxt17(MACRO, SEP, CONTEXT) \
|
||||
metamacro_for_cxt16(MACRO, SEP, CONTEXT) \
|
||||
SEP \
|
||||
MACRO(16, CONTEXT)
|
||||
|
||||
#define metamacro_for_cxt18(MACRO, SEP, CONTEXT) \
|
||||
metamacro_for_cxt17(MACRO, SEP, CONTEXT) \
|
||||
SEP \
|
||||
MACRO(17, CONTEXT)
|
||||
|
||||
#define metamacro_for_cxt19(MACRO, SEP, CONTEXT) \
|
||||
metamacro_for_cxt18(MACRO, SEP, CONTEXT) \
|
||||
SEP \
|
||||
MACRO(18, CONTEXT)
|
||||
|
||||
#define metamacro_for_cxt20(MACRO, SEP, CONTEXT) \
|
||||
metamacro_for_cxt19(MACRO, SEP, CONTEXT) \
|
||||
SEP \
|
||||
MACRO(19, CONTEXT)
|
||||
|
||||
// metamacro_if_eq expansions
|
||||
#define metamacro_if_eq0(VALUE) \
|
||||
metamacro_concat(metamacro_if_eq0_, VALUE)
|
||||
|
||||
#define metamacro_if_eq0_0(...) __VA_ARGS__ metamacro_consume_
|
||||
#define metamacro_if_eq0_1(...) metamacro_expand_
|
||||
#define metamacro_if_eq0_2(...) metamacro_expand_
|
||||
#define metamacro_if_eq0_3(...) metamacro_expand_
|
||||
#define metamacro_if_eq0_4(...) metamacro_expand_
|
||||
#define metamacro_if_eq0_5(...) metamacro_expand_
|
||||
#define metamacro_if_eq0_6(...) metamacro_expand_
|
||||
#define metamacro_if_eq0_7(...) metamacro_expand_
|
||||
#define metamacro_if_eq0_8(...) metamacro_expand_
|
||||
#define metamacro_if_eq0_9(...) metamacro_expand_
|
||||
#define metamacro_if_eq0_10(...) metamacro_expand_
|
||||
#define metamacro_if_eq0_11(...) metamacro_expand_
|
||||
#define metamacro_if_eq0_12(...) metamacro_expand_
|
||||
#define metamacro_if_eq0_13(...) metamacro_expand_
|
||||
#define metamacro_if_eq0_14(...) metamacro_expand_
|
||||
#define metamacro_if_eq0_15(...) metamacro_expand_
|
||||
#define metamacro_if_eq0_16(...) metamacro_expand_
|
||||
#define metamacro_if_eq0_17(...) metamacro_expand_
|
||||
#define metamacro_if_eq0_18(...) metamacro_expand_
|
||||
#define metamacro_if_eq0_19(...) metamacro_expand_
|
||||
#define metamacro_if_eq0_20(...) metamacro_expand_
|
||||
|
||||
#define metamacro_if_eq1(VALUE) metamacro_if_eq0(metamacro_dec(VALUE))
|
||||
#define metamacro_if_eq2(VALUE) metamacro_if_eq1(metamacro_dec(VALUE))
|
||||
#define metamacro_if_eq3(VALUE) metamacro_if_eq2(metamacro_dec(VALUE))
|
||||
#define metamacro_if_eq4(VALUE) metamacro_if_eq3(metamacro_dec(VALUE))
|
||||
#define metamacro_if_eq5(VALUE) metamacro_if_eq4(metamacro_dec(VALUE))
|
||||
#define metamacro_if_eq6(VALUE) metamacro_if_eq5(metamacro_dec(VALUE))
|
||||
#define metamacro_if_eq7(VALUE) metamacro_if_eq6(metamacro_dec(VALUE))
|
||||
#define metamacro_if_eq8(VALUE) metamacro_if_eq7(metamacro_dec(VALUE))
|
||||
#define metamacro_if_eq9(VALUE) metamacro_if_eq8(metamacro_dec(VALUE))
|
||||
#define metamacro_if_eq10(VALUE) metamacro_if_eq9(metamacro_dec(VALUE))
|
||||
#define metamacro_if_eq11(VALUE) metamacro_if_eq10(metamacro_dec(VALUE))
|
||||
#define metamacro_if_eq12(VALUE) metamacro_if_eq11(metamacro_dec(VALUE))
|
||||
#define metamacro_if_eq13(VALUE) metamacro_if_eq12(metamacro_dec(VALUE))
|
||||
#define metamacro_if_eq14(VALUE) metamacro_if_eq13(metamacro_dec(VALUE))
|
||||
#define metamacro_if_eq15(VALUE) metamacro_if_eq14(metamacro_dec(VALUE))
|
||||
#define metamacro_if_eq16(VALUE) metamacro_if_eq15(metamacro_dec(VALUE))
|
||||
#define metamacro_if_eq17(VALUE) metamacro_if_eq16(metamacro_dec(VALUE))
|
||||
#define metamacro_if_eq18(VALUE) metamacro_if_eq17(metamacro_dec(VALUE))
|
||||
#define metamacro_if_eq19(VALUE) metamacro_if_eq18(metamacro_dec(VALUE))
|
||||
#define metamacro_if_eq20(VALUE) metamacro_if_eq19(metamacro_dec(VALUE))
|
||||
|
||||
// metamacro_if_eq_recursive expansions
|
||||
#define metamacro_if_eq_recursive0(VALUE) \
|
||||
metamacro_concat(metamacro_if_eq_recursive0_, VALUE)
|
||||
|
||||
#define metamacro_if_eq_recursive0_0(...) __VA_ARGS__ metamacro_consume_
|
||||
#define metamacro_if_eq_recursive0_1(...) metamacro_expand_
|
||||
#define metamacro_if_eq_recursive0_2(...) metamacro_expand_
|
||||
#define metamacro_if_eq_recursive0_3(...) metamacro_expand_
|
||||
#define metamacro_if_eq_recursive0_4(...) metamacro_expand_
|
||||
#define metamacro_if_eq_recursive0_5(...) metamacro_expand_
|
||||
#define metamacro_if_eq_recursive0_6(...) metamacro_expand_
|
||||
#define metamacro_if_eq_recursive0_7(...) metamacro_expand_
|
||||
#define metamacro_if_eq_recursive0_8(...) metamacro_expand_
|
||||
#define metamacro_if_eq_recursive0_9(...) metamacro_expand_
|
||||
#define metamacro_if_eq_recursive0_10(...) metamacro_expand_
|
||||
#define metamacro_if_eq_recursive0_11(...) metamacro_expand_
|
||||
#define metamacro_if_eq_recursive0_12(...) metamacro_expand_
|
||||
#define metamacro_if_eq_recursive0_13(...) metamacro_expand_
|
||||
#define metamacro_if_eq_recursive0_14(...) metamacro_expand_
|
||||
#define metamacro_if_eq_recursive0_15(...) metamacro_expand_
|
||||
#define metamacro_if_eq_recursive0_16(...) metamacro_expand_
|
||||
#define metamacro_if_eq_recursive0_17(...) metamacro_expand_
|
||||
#define metamacro_if_eq_recursive0_18(...) metamacro_expand_
|
||||
#define metamacro_if_eq_recursive0_19(...) metamacro_expand_
|
||||
#define metamacro_if_eq_recursive0_20(...) metamacro_expand_
|
||||
|
||||
#define metamacro_if_eq_recursive1(VALUE) metamacro_if_eq_recursive0(metamacro_dec(VALUE))
|
||||
#define metamacro_if_eq_recursive2(VALUE) metamacro_if_eq_recursive1(metamacro_dec(VALUE))
|
||||
#define metamacro_if_eq_recursive3(VALUE) metamacro_if_eq_recursive2(metamacro_dec(VALUE))
|
||||
#define metamacro_if_eq_recursive4(VALUE) metamacro_if_eq_recursive3(metamacro_dec(VALUE))
|
||||
#define metamacro_if_eq_recursive5(VALUE) metamacro_if_eq_recursive4(metamacro_dec(VALUE))
|
||||
#define metamacro_if_eq_recursive6(VALUE) metamacro_if_eq_recursive5(metamacro_dec(VALUE))
|
||||
#define metamacro_if_eq_recursive7(VALUE) metamacro_if_eq_recursive6(metamacro_dec(VALUE))
|
||||
#define metamacro_if_eq_recursive8(VALUE) metamacro_if_eq_recursive7(metamacro_dec(VALUE))
|
||||
#define metamacro_if_eq_recursive9(VALUE) metamacro_if_eq_recursive8(metamacro_dec(VALUE))
|
||||
#define metamacro_if_eq_recursive10(VALUE) metamacro_if_eq_recursive9(metamacro_dec(VALUE))
|
||||
#define metamacro_if_eq_recursive11(VALUE) metamacro_if_eq_recursive10(metamacro_dec(VALUE))
|
||||
#define metamacro_if_eq_recursive12(VALUE) metamacro_if_eq_recursive11(metamacro_dec(VALUE))
|
||||
#define metamacro_if_eq_recursive13(VALUE) metamacro_if_eq_recursive12(metamacro_dec(VALUE))
|
||||
#define metamacro_if_eq_recursive14(VALUE) metamacro_if_eq_recursive13(metamacro_dec(VALUE))
|
||||
#define metamacro_if_eq_recursive15(VALUE) metamacro_if_eq_recursive14(metamacro_dec(VALUE))
|
||||
#define metamacro_if_eq_recursive16(VALUE) metamacro_if_eq_recursive15(metamacro_dec(VALUE))
|
||||
#define metamacro_if_eq_recursive17(VALUE) metamacro_if_eq_recursive16(metamacro_dec(VALUE))
|
||||
#define metamacro_if_eq_recursive18(VALUE) metamacro_if_eq_recursive17(metamacro_dec(VALUE))
|
||||
#define metamacro_if_eq_recursive19(VALUE) metamacro_if_eq_recursive18(metamacro_dec(VALUE))
|
||||
#define metamacro_if_eq_recursive20(VALUE) metamacro_if_eq_recursive19(metamacro_dec(VALUE))
|
||||
|
||||
// metamacro_take expansions
|
||||
#define metamacro_take0(...)
|
||||
#define metamacro_take1(...) metamacro_head(__VA_ARGS__)
|
||||
#define metamacro_take2(...) metamacro_head(__VA_ARGS__), metamacro_take1(metamacro_tail(__VA_ARGS__))
|
||||
#define metamacro_take3(...) metamacro_head(__VA_ARGS__), metamacro_take2(metamacro_tail(__VA_ARGS__))
|
||||
#define metamacro_take4(...) metamacro_head(__VA_ARGS__), metamacro_take3(metamacro_tail(__VA_ARGS__))
|
||||
#define metamacro_take5(...) metamacro_head(__VA_ARGS__), metamacro_take4(metamacro_tail(__VA_ARGS__))
|
||||
#define metamacro_take6(...) metamacro_head(__VA_ARGS__), metamacro_take5(metamacro_tail(__VA_ARGS__))
|
||||
#define metamacro_take7(...) metamacro_head(__VA_ARGS__), metamacro_take6(metamacro_tail(__VA_ARGS__))
|
||||
#define metamacro_take8(...) metamacro_head(__VA_ARGS__), metamacro_take7(metamacro_tail(__VA_ARGS__))
|
||||
#define metamacro_take9(...) metamacro_head(__VA_ARGS__), metamacro_take8(metamacro_tail(__VA_ARGS__))
|
||||
#define metamacro_take10(...) metamacro_head(__VA_ARGS__), metamacro_take9(metamacro_tail(__VA_ARGS__))
|
||||
#define metamacro_take11(...) metamacro_head(__VA_ARGS__), metamacro_take10(metamacro_tail(__VA_ARGS__))
|
||||
#define metamacro_take12(...) metamacro_head(__VA_ARGS__), metamacro_take11(metamacro_tail(__VA_ARGS__))
|
||||
#define metamacro_take13(...) metamacro_head(__VA_ARGS__), metamacro_take12(metamacro_tail(__VA_ARGS__))
|
||||
#define metamacro_take14(...) metamacro_head(__VA_ARGS__), metamacro_take13(metamacro_tail(__VA_ARGS__))
|
||||
#define metamacro_take15(...) metamacro_head(__VA_ARGS__), metamacro_take14(metamacro_tail(__VA_ARGS__))
|
||||
#define metamacro_take16(...) metamacro_head(__VA_ARGS__), metamacro_take15(metamacro_tail(__VA_ARGS__))
|
||||
#define metamacro_take17(...) metamacro_head(__VA_ARGS__), metamacro_take16(metamacro_tail(__VA_ARGS__))
|
||||
#define metamacro_take18(...) metamacro_head(__VA_ARGS__), metamacro_take17(metamacro_tail(__VA_ARGS__))
|
||||
#define metamacro_take19(...) metamacro_head(__VA_ARGS__), metamacro_take18(metamacro_tail(__VA_ARGS__))
|
||||
#define metamacro_take20(...) metamacro_head(__VA_ARGS__), metamacro_take19(metamacro_tail(__VA_ARGS__))
|
||||
|
||||
// metamacro_drop expansions
|
||||
#define metamacro_drop0(...) __VA_ARGS__
|
||||
#define metamacro_drop1(...) metamacro_tail(__VA_ARGS__)
|
||||
#define metamacro_drop2(...) metamacro_drop1(metamacro_tail(__VA_ARGS__))
|
||||
#define metamacro_drop3(...) metamacro_drop2(metamacro_tail(__VA_ARGS__))
|
||||
#define metamacro_drop4(...) metamacro_drop3(metamacro_tail(__VA_ARGS__))
|
||||
#define metamacro_drop5(...) metamacro_drop4(metamacro_tail(__VA_ARGS__))
|
||||
#define metamacro_drop6(...) metamacro_drop5(metamacro_tail(__VA_ARGS__))
|
||||
#define metamacro_drop7(...) metamacro_drop6(metamacro_tail(__VA_ARGS__))
|
||||
#define metamacro_drop8(...) metamacro_drop7(metamacro_tail(__VA_ARGS__))
|
||||
#define metamacro_drop9(...) metamacro_drop8(metamacro_tail(__VA_ARGS__))
|
||||
#define metamacro_drop10(...) metamacro_drop9(metamacro_tail(__VA_ARGS__))
|
||||
#define metamacro_drop11(...) metamacro_drop10(metamacro_tail(__VA_ARGS__))
|
||||
#define metamacro_drop12(...) metamacro_drop11(metamacro_tail(__VA_ARGS__))
|
||||
#define metamacro_drop13(...) metamacro_drop12(metamacro_tail(__VA_ARGS__))
|
||||
#define metamacro_drop14(...) metamacro_drop13(metamacro_tail(__VA_ARGS__))
|
||||
#define metamacro_drop15(...) metamacro_drop14(metamacro_tail(__VA_ARGS__))
|
||||
#define metamacro_drop16(...) metamacro_drop15(metamacro_tail(__VA_ARGS__))
|
||||
#define metamacro_drop17(...) metamacro_drop16(metamacro_tail(__VA_ARGS__))
|
||||
#define metamacro_drop18(...) metamacro_drop17(metamacro_tail(__VA_ARGS__))
|
||||
#define metamacro_drop19(...) metamacro_drop18(metamacro_tail(__VA_ARGS__))
|
||||
#define metamacro_drop20(...) metamacro_drop19(metamacro_tail(__VA_ARGS__))
|
||||
|
||||
#endif
|
|
@ -407,8 +407,9 @@
|
|||
}
|
||||
return;
|
||||
}
|
||||
__weak typeof(self) wself = self;
|
||||
@weakify(self);
|
||||
[cache queryImageForKey:key options:options context:context completion:^(UIImage * _Nullable image, NSData * _Nullable data, SDImageCacheType cacheType) {
|
||||
@strongify(self);
|
||||
if (operation.isCancelled) {
|
||||
// Cancelled
|
||||
return;
|
||||
|
@ -427,7 +428,7 @@
|
|||
return;
|
||||
}
|
||||
// Next
|
||||
[wself serialQueryImageForKey:key options:options context:context completion:completionBlock enumerator:enumerator operation:operation];
|
||||
[self serialQueryImageForKey:key options:options context:context completion:completionBlock enumerator:enumerator operation:operation];
|
||||
}];
|
||||
}
|
||||
|
||||
|
@ -441,10 +442,11 @@
|
|||
}
|
||||
return;
|
||||
}
|
||||
__weak typeof(self) wself = self;
|
||||
@weakify(self);
|
||||
[cache storeImage:image imageData:imageData forKey:key cacheType:cacheType completion:^{
|
||||
@strongify(self);
|
||||
// Next
|
||||
[wself serialStoreImage:image imageData:imageData forKey:key cacheType:cacheType completion:completionBlock enumerator:enumerator];
|
||||
[self serialStoreImage:image imageData:imageData forKey:key cacheType:cacheType completion:completionBlock enumerator:enumerator];
|
||||
}];
|
||||
}
|
||||
|
||||
|
@ -458,10 +460,11 @@
|
|||
}
|
||||
return;
|
||||
}
|
||||
__weak typeof(self) wself = self;
|
||||
@weakify(self);
|
||||
[cache removeImageForKey:key cacheType:cacheType completion:^{
|
||||
@strongify(self);
|
||||
// Next
|
||||
[wself serialRemoveImageForKey:key cacheType:cacheType completion:completionBlock enumerator:enumerator];
|
||||
[self serialRemoveImageForKey:key cacheType:cacheType completion:completionBlock enumerator:enumerator];
|
||||
}];
|
||||
}
|
||||
|
||||
|
@ -477,8 +480,9 @@
|
|||
}
|
||||
return;
|
||||
}
|
||||
__weak typeof(self) wself = self;
|
||||
@weakify(self);
|
||||
[cache containsImageForKey:key cacheType:cacheType completion:^(SDImageCacheType containsCacheType) {
|
||||
@strongify(self);
|
||||
if (operation.isCancelled) {
|
||||
// Cancelled
|
||||
return;
|
||||
|
@ -497,7 +501,7 @@
|
|||
return;
|
||||
}
|
||||
// Next
|
||||
[wself serialContainsImageForKey:key cacheType:cacheType completion:completionBlock enumerator:enumerator operation:operation];
|
||||
[self serialContainsImageForKey:key cacheType:cacheType completion:completionBlock enumerator:enumerator operation:operation];
|
||||
}];
|
||||
}
|
||||
|
||||
|
@ -511,10 +515,11 @@
|
|||
}
|
||||
return;
|
||||
}
|
||||
__weak typeof(self) wself = self;
|
||||
@weakify(self);
|
||||
[cache clearWithCacheType:cacheType completion:^{
|
||||
@strongify(self);
|
||||
// Next
|
||||
[wself serialClearWithCacheType:cacheType completion:completionBlock enumerator:enumerator];
|
||||
[self serialClearWithCacheType:cacheType completion:completionBlock enumerator:enumerator];
|
||||
}];
|
||||
}
|
||||
|
||||
|
|
|
@ -93,11 +93,3 @@
|
|||
dispatch_async(dispatch_get_main_queue(), block);\
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef SD_LOCK
|
||||
#define SD_LOCK(lock) dispatch_semaphore_wait(lock, DISPATCH_TIME_FOREVER);
|
||||
#endif
|
||||
|
||||
#ifndef SD_UNLOCK
|
||||
#define SD_UNLOCK(lock) dispatch_semaphore_signal(lock);
|
||||
#endif
|
||||
|
|
|
@ -202,15 +202,15 @@ static void * SDWebImageDownloaderContext = &SDWebImageDownloaderContext;
|
|||
}
|
||||
return nil;
|
||||
}
|
||||
__weak typeof(self) wself = self;
|
||||
@weakify(self);
|
||||
operation.completionBlock = ^{
|
||||
__strong typeof(wself) sself = wself;
|
||||
if (!sself) {
|
||||
@strongify(self);
|
||||
if (!self) {
|
||||
return;
|
||||
}
|
||||
SD_LOCK(sself.operationsLock);
|
||||
[sself.URLOperations removeObjectForKey:url];
|
||||
SD_UNLOCK(sself.operationsLock);
|
||||
SD_LOCK(self.operationsLock);
|
||||
[self.URLOperations removeObjectForKey:url];
|
||||
SD_UNLOCK(self.operationsLock);
|
||||
};
|
||||
self.URLOperations[url] = operation;
|
||||
// Add operation to operation queue only after all configuration done according to Apple's doc.
|
||||
|
|
|
@ -141,7 +141,7 @@ typedef NSMutableDictionary<NSString *, id> SDCallbacksDictionary;
|
|||
Class UIApplicationClass = NSClassFromString(@"UIApplication");
|
||||
BOOL hasApplication = UIApplicationClass && [UIApplicationClass respondsToSelector:@selector(sharedApplication)];
|
||||
if (hasApplication && [self shouldContinueWhenAppEntersBackground]) {
|
||||
__weak __typeof__ (self) wself = self;
|
||||
__weak typeof(self) wself = self;
|
||||
UIApplication * app = [UIApplicationClass performSelector:@selector(sharedApplication)];
|
||||
self.backgroundTaskId = [app beginBackgroundTaskWithExpirationHandler:^{
|
||||
[wself cancel];
|
||||
|
|
|
@ -188,15 +188,15 @@ static id<SDImageLoader> _defaultImageLoader;
|
|||
if (shouldQueryCache) {
|
||||
id<SDWebImageCacheKeyFilter> cacheKeyFilter = context[SDWebImageContextCacheKeyFilter];
|
||||
NSString *key = [self cacheKeyForURL:url cacheKeyFilter:cacheKeyFilter];
|
||||
__weak SDWebImageCombinedOperation *weakOperation = operation;
|
||||
@weakify(operation);
|
||||
operation.cacheOperation = [self.imageCache queryImageForKey:key options:options context:context completion:^(UIImage * _Nullable cachedImage, NSData * _Nullable cachedData, SDImageCacheType cacheType) {
|
||||
__strong __typeof(weakOperation) strongOperation = weakOperation;
|
||||
if (!strongOperation || strongOperation.isCancelled) {
|
||||
[self safelyRemoveOperationFromRunning:strongOperation];
|
||||
@strongify(operation);
|
||||
if (!operation || operation.isCancelled) {
|
||||
[self safelyRemoveOperationFromRunning:operation];
|
||||
return;
|
||||
}
|
||||
// Continue download process
|
||||
[self callDownloadProcessForOperation:strongOperation url:url options:options context:context cachedImage:cachedImage cachedData:cachedData cacheType:cacheType progress:progressBlock completed:completedBlock];
|
||||
[self callDownloadProcessForOperation:operation url:url options:options context:context cachedImage:cachedImage cachedData:cachedData cacheType:cacheType progress:progressBlock completed:completedBlock];
|
||||
}];
|
||||
} else {
|
||||
// Continue download process
|
||||
|
@ -236,17 +236,17 @@ static id<SDImageLoader> _defaultImageLoader;
|
|||
}
|
||||
|
||||
// `SDWebImageCombinedOperation` -> `SDWebImageDownloadToken` -> `downloadOperationCancelToken`, which is a `SDCallbacksDictionary` and retain the completed block below, so we need weak-strong again to avoid retain cycle
|
||||
__weak typeof(operation) weakOperation = operation;
|
||||
@weakify(operation);
|
||||
operation.loaderOperation = [self.imageLoader loadImageWithURL:url options:options context:context progress:progressBlock completed:^(UIImage *downloadedImage, NSData *downloadedData, NSError *error, BOOL finished) {
|
||||
__strong typeof(weakOperation) strongOperation = weakOperation;
|
||||
if (!strongOperation || strongOperation.isCancelled) {
|
||||
@strongify(operation);
|
||||
if (!operation || operation.isCancelled) {
|
||||
// Do nothing if the operation was cancelled
|
||||
// See #699 for more details
|
||||
// if we would call the completedBlock, there could be a race condition between this block and another completedBlock for the same object, so if this one is called second, we will overwrite the new data
|
||||
} else if (cachedImage && options & SDWebImageRefreshCached && [error.domain isEqualToString:SDWebImageErrorDomain] && error.code == SDWebImageErrorCacheNotModified) {
|
||||
// Image refresh hit the NSURLCache cache, do not call the completion block
|
||||
} else if (error) {
|
||||
[self callCompletionBlockForOperation:strongOperation completion:completedBlock error:error url:url];
|
||||
[self callCompletionBlockForOperation:operation completion:completedBlock error:error url:url];
|
||||
BOOL shouldBlockFailedURL = [self shouldBlockFailedURLWithURL:url error:error];
|
||||
|
||||
if (shouldBlockFailedURL) {
|
||||
|
@ -261,11 +261,11 @@ static id<SDImageLoader> _defaultImageLoader;
|
|||
SD_UNLOCK(self.failedURLsLock);
|
||||
}
|
||||
|
||||
[self callStoreCacheProcessForOperation:strongOperation url:url options:options context:context downloadedImage:downloadedImage downloadedData:downloadedData finished:finished progress:progressBlock completed:completedBlock];
|
||||
[self callStoreCacheProcessForOperation:operation url:url options:options context:context downloadedImage:downloadedImage downloadedData:downloadedData finished:finished progress:progressBlock completed:completedBlock];
|
||||
}
|
||||
|
||||
if (finished) {
|
||||
[self safelyRemoveOperationFromRunning:strongOperation];
|
||||
[self safelyRemoveOperationFromRunning:operation];
|
||||
}
|
||||
}];
|
||||
} else if (cachedImage) {
|
||||
|
|
|
@ -107,39 +107,38 @@
|
|||
- (void)startPrefetchWithToken:(SDWebImagePrefetchToken * _Nonnull)token {
|
||||
NSPointerArray *operations = token.loadOperations;
|
||||
for (NSURL *url in token.urls) {
|
||||
__weak typeof(self) wself = self;
|
||||
@weakify(self);
|
||||
SDAsyncBlockOperation *prefetchOperation = [SDAsyncBlockOperation blockOperationWithBlock:^(SDAsyncBlockOperation * _Nonnull asyncOperation) {
|
||||
__strong typeof(wself) strongSelf = wself;
|
||||
if (!strongSelf || asyncOperation.isCancelled) {
|
||||
return;
|
||||
}
|
||||
id<SDWebImageOperation> operation = [strongSelf.manager loadImageWithURL:url options:strongSelf.options context:strongSelf.context progress:nil completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, SDImageCacheType cacheType, BOOL finished, NSURL * _Nullable imageURL) {
|
||||
__strong typeof(wself) sself = wself;
|
||||
if (!sself) {
|
||||
return;
|
||||
}
|
||||
if (!finished) {
|
||||
return;
|
||||
}
|
||||
|
||||
atomic_fetch_add_explicit(&(token->_finishedCount), 1, memory_order_relaxed);
|
||||
if (error) {
|
||||
// Add last failed
|
||||
atomic_fetch_add_explicit(&(token->_skippedCount), 1, memory_order_relaxed);
|
||||
}
|
||||
|
||||
// Current operation finished
|
||||
[sself callProgressBlockForToken:token imageURL:imageURL];
|
||||
|
||||
if (atomic_load_explicit(&(token->_finishedCount), memory_order_relaxed) == token->_totalCount) {
|
||||
// All finished
|
||||
if (!atomic_flag_test_and_set_explicit(&(token->_isAllFinished), memory_order_relaxed)) {
|
||||
[sself callCompletionBlockForToken:token];
|
||||
[sself removeRunningToken:token];
|
||||
}
|
||||
}
|
||||
[asyncOperation complete];
|
||||
}];
|
||||
@strongify(self);
|
||||
if (!self || asyncOperation.isCancelled) {
|
||||
return;
|
||||
}
|
||||
id<SDWebImageOperation> operation = [self.manager loadImageWithURL:url options:self.options context:self.context progress:nil completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, SDImageCacheType cacheType, BOOL finished, NSURL * _Nullable imageURL) {
|
||||
@strongify(self);
|
||||
if (!self) {
|
||||
return;
|
||||
}
|
||||
if (!finished) {
|
||||
return;
|
||||
}
|
||||
atomic_fetch_add_explicit(&(token->_finishedCount), 1, memory_order_relaxed);
|
||||
if (error) {
|
||||
// Add last failed
|
||||
atomic_fetch_add_explicit(&(token->_skippedCount), 1, memory_order_relaxed);
|
||||
}
|
||||
|
||||
// Current operation finished
|
||||
[self callProgressBlockForToken:token imageURL:imageURL];
|
||||
|
||||
if (atomic_load_explicit(&(token->_finishedCount), memory_order_relaxed) == token->_totalCount) {
|
||||
// All finished
|
||||
if (!atomic_flag_test_and_set_explicit(&(token->_isAllFinished), memory_order_relaxed)) {
|
||||
[self callCompletionBlockForToken:token];
|
||||
[self removeRunningToken:token];
|
||||
}
|
||||
}
|
||||
[asyncOperation complete];
|
||||
}];
|
||||
NSAssert(operation != nil, @"Operation should not be nil, [SDWebImageManager loadImageWithURL:options:context:progress:completed:] break prefetch logic");
|
||||
@synchronized (token) {
|
||||
[operations addPointer:(__bridge void *)operation];
|
||||
|
|
|
@ -73,10 +73,10 @@ const int64_t SDWebImageProgressUnitCountUnknown = 1LL;
|
|||
manager = [SDWebImageManager sharedManager];
|
||||
}
|
||||
|
||||
__weak __typeof(self)wself = self;
|
||||
@weakify(self);
|
||||
SDImageLoaderProgressBlock combinedProgressBlock = ^(NSInteger receivedSize, NSInteger expectedSize, NSURL * _Nullable targetURL) {
|
||||
__strong __typeof (wself) sself = wself;
|
||||
NSProgress *imageProgress = sself.sd_imageProgress;
|
||||
@strongify(self);
|
||||
NSProgress *imageProgress = self.sd_imageProgress;
|
||||
imageProgress.totalUnitCount = expectedSize;
|
||||
imageProgress.completedUnitCount = receivedSize;
|
||||
#if SD_UIKIT || SD_MAC
|
||||
|
@ -92,12 +92,12 @@ const int64_t SDWebImageProgressUnitCountUnknown = 1LL;
|
|||
}
|
||||
};
|
||||
id <SDWebImageOperation> operation = [manager loadImageWithURL:url options:options context:context progress:combinedProgressBlock completed:^(UIImage *image, NSData *data, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
|
||||
__strong __typeof (wself) sself = wself;
|
||||
if (!sself) { return; }
|
||||
@strongify(self);
|
||||
if (!self) { return; }
|
||||
// if the progress not been updated, mark it to complete state
|
||||
if (finished && !error && sself.sd_imageProgress.totalUnitCount == 0 && sself.sd_imageProgress.completedUnitCount == 0) {
|
||||
sself.sd_imageProgress.totalUnitCount = SDWebImageProgressUnitCountUnknown;
|
||||
sself.sd_imageProgress.completedUnitCount = SDWebImageProgressUnitCountUnknown;
|
||||
if (finished && !error && self.sd_imageProgress.totalUnitCount == 0 && self.sd_imageProgress.completedUnitCount == 0) {
|
||||
self.sd_imageProgress.totalUnitCount = SDWebImageProgressUnitCountUnknown;
|
||||
self.sd_imageProgress.completedUnitCount = SDWebImageProgressUnitCountUnknown;
|
||||
}
|
||||
|
||||
#if SD_UIKIT || SD_MAC
|
||||
|
@ -111,9 +111,9 @@ const int64_t SDWebImageProgressUnitCountUnknown = 1LL;
|
|||
BOOL shouldNotSetImage = ((image && (options & SDWebImageAvoidAutoSetImage)) ||
|
||||
(!image && !(options & SDWebImageDelayPlaceholder)));
|
||||
SDWebImageNoParamsBlock callCompletedBlockClojure = ^{
|
||||
if (!sself) { return; }
|
||||
if (!self) { return; }
|
||||
if (!shouldNotSetImage) {
|
||||
[sself sd_setNeedsLayout];
|
||||
[self sd_setNeedsLayout];
|
||||
}
|
||||
if (completedBlock && shouldCallCompletedBlock) {
|
||||
completedBlock(image, data, error, cacheType, finished, url);
|
||||
|
@ -144,14 +144,14 @@ const int64_t SDWebImageProgressUnitCountUnknown = 1LL;
|
|||
// check whether we should use the image transition
|
||||
SDWebImageTransition *transition = nil;
|
||||
if (finished && (options & SDWebImageForceTransition || cacheType == SDImageCacheTypeNone)) {
|
||||
transition = sself.sd_imageTransition;
|
||||
transition = self.sd_imageTransition;
|
||||
}
|
||||
#endif
|
||||
dispatch_main_async_safe(^{
|
||||
#if SD_UIKIT || SD_MAC
|
||||
[sself sd_setImage:targetImage imageData:targetData basedOnClassOrViaCustomSetImageBlock:setImageBlock transition:transition cacheType:cacheType imageURL:imageURL];
|
||||
[self sd_setImage:targetImage imageData:targetData basedOnClassOrViaCustomSetImageBlock:setImageBlock transition:transition cacheType:cacheType imageURL:imageURL];
|
||||
#else
|
||||
[sself sd_setImage:targetImage imageData:targetData basedOnClassOrViaCustomSetImageBlock:setImageBlock cacheType:cacheType imageURL:imageURL];
|
||||
[self sd_setImage:targetImage imageData:targetData basedOnClassOrViaCustomSetImageBlock:setImageBlock cacheType:cacheType imageURL:imageURL];
|
||||
#endif
|
||||
callCompletedBlockClojure();
|
||||
});
|
||||
|
|
|
@ -22,6 +22,12 @@
|
|||
327054E3206CEFF3006EA328 /* TestImageAnimated.apng in Resources */ = {isa = PBXBuildFile; fileRef = 327054E1206CEFF3006EA328 /* TestImageAnimated.apng */; };
|
||||
327A418C211D660600495442 /* TestImage.heic in Resources */ = {isa = PBXBuildFile; fileRef = 327A418B211D660600495442 /* TestImage.heic */; };
|
||||
327A418D211D660600495442 /* TestImage.heic in Resources */ = {isa = PBXBuildFile; fileRef = 327A418B211D660600495442 /* TestImage.heic */; };
|
||||
328BAF292240C08E00FC70DD /* Test-Shared.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 328BAF262240C08E00FC70DD /* Test-Shared.xcconfig */; };
|
||||
328BAF2A2240C08E00FC70DD /* Test-Shared.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 328BAF262240C08E00FC70DD /* Test-Shared.xcconfig */; };
|
||||
328BAF2B2240C08E00FC70DD /* Test-Release.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 328BAF272240C08E00FC70DD /* Test-Release.xcconfig */; };
|
||||
328BAF2C2240C08E00FC70DD /* Test-Release.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 328BAF272240C08E00FC70DD /* Test-Release.xcconfig */; };
|
||||
328BAF2D2240C08E00FC70DD /* Test-Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 328BAF282240C08E00FC70DD /* Test-Debug.xcconfig */; };
|
||||
328BAF2E2240C08E00FC70DD /* Test-Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 328BAF282240C08E00FC70DD /* Test-Debug.xcconfig */; };
|
||||
328BB6DD20825E9800760D6C /* SDWebImageTestCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 328BB6DC20825E9800760D6C /* SDWebImageTestCache.m */; };
|
||||
328BB6DE20825E9800760D6C /* SDWebImageTestCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 328BB6DC20825E9800760D6C /* SDWebImageTestCache.m */; };
|
||||
32905E64211D786E00460FCF /* TestImage.heif in Resources */ = {isa = PBXBuildFile; fileRef = 32905E63211D786E00460FCF /* TestImage.heif */; };
|
||||
|
@ -78,6 +84,9 @@
|
|||
3264FF2E205D42CB00F6BD48 /* SDWebImageTestTransformer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDWebImageTestTransformer.m; sourceTree = "<group>"; };
|
||||
327054E1206CEFF3006EA328 /* TestImageAnimated.apng */ = {isa = PBXFileReference; lastKnownFileType = file; path = TestImageAnimated.apng; sourceTree = "<group>"; };
|
||||
327A418B211D660600495442 /* TestImage.heic */ = {isa = PBXFileReference; lastKnownFileType = file; path = TestImage.heic; sourceTree = "<group>"; };
|
||||
328BAF262240C08E00FC70DD /* Test-Shared.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "Test-Shared.xcconfig"; sourceTree = "<group>"; };
|
||||
328BAF272240C08E00FC70DD /* Test-Release.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "Test-Release.xcconfig"; sourceTree = "<group>"; };
|
||||
328BAF282240C08E00FC70DD /* Test-Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "Test-Debug.xcconfig"; sourceTree = "<group>"; };
|
||||
328BB6DB20825E9800760D6C /* SDWebImageTestCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDWebImageTestCache.h; sourceTree = "<group>"; };
|
||||
328BB6DC20825E9800760D6C /* SDWebImageTestCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDWebImageTestCache.m; sourceTree = "<group>"; };
|
||||
32905E63211D786E00460FCF /* TestImage.heif */ = {isa = PBXFileReference; lastKnownFileType = file; path = TestImage.heif; sourceTree = "<group>"; };
|
||||
|
@ -253,6 +262,9 @@
|
|||
EADD19EC219915E300804BB0 /* Module-Debug.xcconfig */,
|
||||
EADD19E9219915E300804BB0 /* Module-Release.xcconfig */,
|
||||
EADD19EE219915E300804BB0 /* Module-Shared.xcconfig */,
|
||||
328BAF282240C08E00FC70DD /* Test-Debug.xcconfig */,
|
||||
328BAF272240C08E00FC70DD /* Test-Release.xcconfig */,
|
||||
328BAF262240C08E00FC70DD /* Test-Shared.xcconfig */,
|
||||
);
|
||||
name = Configs;
|
||||
path = ../Configs;
|
||||
|
@ -338,12 +350,15 @@
|
|||
files = (
|
||||
327054E3206CEFF3006EA328 /* TestImageAnimated.apng in Resources */,
|
||||
32B99EA3203B31360017FD66 /* TestImage.gif in Resources */,
|
||||
328BAF2C2240C08E00FC70DD /* Test-Release.xcconfig in Resources */,
|
||||
328BAF2E2240C08E00FC70DD /* Test-Debug.xcconfig in Resources */,
|
||||
32B99EA4203B31360017FD66 /* TestImage.jpg in Resources */,
|
||||
32B99EA6203B31360017FD66 /* TestImage.png in Resources */,
|
||||
32B99EA2203B31360017FD66 /* MonochromeTestImage.jpg in Resources */,
|
||||
32905E65211D786E00460FCF /* TestImage.heif in Resources */,
|
||||
327A418D211D660600495442 /* TestImage.heic in Resources */,
|
||||
32B99EA5203B31360017FD66 /* TestImageLarge.jpg in Resources */,
|
||||
328BAF2A2240C08E00FC70DD /* Test-Shared.xcconfig in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -351,10 +366,13 @@
|
|||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
328BAF2B2240C08E00FC70DD /* Test-Release.xcconfig in Resources */,
|
||||
327A418C211D660600495442 /* TestImage.heic in Resources */,
|
||||
328BAF292240C08E00FC70DD /* Test-Shared.xcconfig in Resources */,
|
||||
5F7F38AD1AE2A77A00B0E330 /* TestImage.jpg in Resources */,
|
||||
32905E64211D786E00460FCF /* TestImage.heif in Resources */,
|
||||
43828A451DA67F9900000E62 /* TestImageLarge.jpg in Resources */,
|
||||
328BAF2D2240C08E00FC70DD /* Test-Debug.xcconfig in Resources */,
|
||||
433BBBB71D7EF8200086B6E9 /* TestImage.gif in Resources */,
|
||||
DA248D61195472AA00390AB0 /* InfoPlist.strings in Resources */,
|
||||
433BBBB91D7EF8260086B6E9 /* TestImage.png in Resources */,
|
||||
|
@ -543,14 +561,14 @@
|
|||
};
|
||||
DA248D4A1954721A00390AB0 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = EADD19EC219915E300804BB0 /* Module-Debug.xcconfig */;
|
||||
baseConfigurationReference = 328BAF282240C08E00FC70DD /* Test-Debug.xcconfig */;
|
||||
buildSettings = {
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
DA248D4B1954721A00390AB0 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = EADD19E9219915E300804BB0 /* Module-Release.xcconfig */;
|
||||
baseConfigurationReference = 328BAF272240C08E00FC70DD /* Test-Release.xcconfig */;
|
||||
buildSettings = {
|
||||
};
|
||||
name = Release;
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
/*
|
||||
* This file is part of the SDWebImage package.
|
||||
* (c) Olivier Poitrey <rs@dailymotion.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
#import "SDInternalMacros.h"
|
Loading…
Reference in New Issue