This repository has been archived by the owner on Nov 2, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 416
/
Copy pathFBTweakInlineInternal.h
210 lines (186 loc) · 10.4 KB
/
FBTweakInlineInternal.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
/**
Copyright (c) 2014-present, Facebook, Inc.
All rights reserved.
This source code is licensed under the BSD-style license found in the
LICENSE file in the root directory of this source tree. An additional grant
of patent rights can be found in the PATENTS file in the same directory.
*/
#import "FBTweakEnabled.h"
#import "FBTweak.h"
#import "FBTweakStore.h"
#import "FBTweakCategory.h"
#import "FBTweakCollection.h"
#import "_FBTweakBindObserver.h"
#if !FB_TWEAK_ENABLED
#define __FBTweakDefault(default, ...) default
#define _FBTweakInline(category_, collection_, name_, ...) nil
#define _FBTweakValue(category_, collection_, name_, ...) (__FBTweakDefault(__VA_ARGS__, _))
#define _FBTweakBind(object_, property_, category_, collection_, name_, ...) (object_.property_ = __FBTweakDefault(__VA_ARGS__, _))
#define _FBTweakAction(category_, collection_, name_, ...)
#else
#ifdef __cplusplus
extern "C" {
#endif
#define FBTweakSegmentName "__DATA"
#define FBTweakSectionName "FBTweak"
#define FBTweakEncodingAction "__ACTION__"
typedef __unsafe_unretained NSString *FBTweakLiteralString;
typedef struct {
FBTweakLiteralString *category;
FBTweakLiteralString *collection;
FBTweakLiteralString *name;
void *value;
void *possible;
char **encoding;
} fb_tweak_entry;
// cast to a pointer to a block, dereferenece said pointer, call said block
#define fb_tweak_entry_block_field(type, entry, field) (*(type (^__unsafe_unretained (*))(void))(entry->field))()
extern NSString *_FBTweakIdentifier(fb_tweak_entry *entry);
#if __has_feature(objc_arc)
#define _FBTweakRelease(x)
#else
#define _FBTweakRelease(x) [x release]
#endif
#define __FBTweakConcat_(X, Y) X ## Y
#define __FBTweakConcat(X, Y) __FBTweakConcat_(X, Y)
#define __FBTweakIndex(_1, _2, _3, value, ...) value
#define __FBTweakIndexCount(...) __FBTweakIndex(__VA_ARGS__, 3, 2, 1)
#define __FBTweakDispatch1(__withoutRange, __withRange, __withPossible, ...) __withoutRange
#define __FBTweakDispatch2(__withoutRange, __withRange, __withPossible, ...) __withPossible
#define __FBTweakDispatch3(__withoutRange, __withRange, __withPossible, ...) __withRange
#define _FBTweakDispatch(__withoutRange, __withRange, __withPossible, ...) __FBTweakConcat(__FBTweakDispatch, __FBTweakIndexCount(__VA_ARGS__))(__withoutRange, __withRange, __withPossible)
#define _FBTweakInlineWithoutRange(category_, collection_, name_, default_) \
((^{ \
return _FBTweakInlineWithPossibleInternal(category_, collection_, name_, default_, NULL); \
})())
#define _FBTweakInlineWithRange(category_, collection_, name_, default_, min_, max_) \
((^{ \
__attribute__((used)) static __typeof__(default_) min__ = (__typeof__(default_))min_; \
__attribute__((used)) static __typeof__(default_) max__ = (__typeof__(default_))max_; \
return _FBTweakInlineWithPossibleInternal(category_, collection_, name_, default_, [[FBTweakNumericRange alloc] initWithMinimumValue:@(min__) maximumValue:@(max__)]); \
})())
#define _FBTweakInlineWithPossible(category_, collection_, name_, default_, possible_) \
((^{ \
return _FBTweakInlineWithPossibleInternal(category_, collection_, name_, default_, possible_); \
})())
#define _FBTweakInlineWithPossibleInternal(category_, collection_, name_, default_, possible_) \
((^{ \
/* store the tweak data in the binary at compile time. */ \
__attribute__((used)) static FBTweakLiteralString category__ = category_; \
__attribute__((used)) static FBTweakLiteralString collection__ = collection_; \
__attribute__((used)) static FBTweakLiteralString name__ = name_; \
__attribute__((used)) static void *default__ = (__bridge void *) ^{ return default_; }; \
__attribute__((used)) static void *possible__ = (__bridge void *) ^{ return possible_; }; \
__attribute__((used)) static char *encoding__ = (char *)@encode(__typeof__(default_)); \
__attribute__((used)) __attribute__((section (FBTweakSegmentName "," FBTweakSectionName))) static fb_tweak_entry entry = \
{ &category__, &collection__, &name__, (void *)&default__, (void *)&possible__, &encoding__ }; \
\
/* find the registered tweak with the given identifier. */ \
FBTweakStore *store = [FBTweakStore sharedInstance]; \
FBTweakCategory *category = [store tweakCategoryWithName:category__]; \
FBTweakCollection *collection = [category tweakCollectionWithName:collection__]; \
\
NSString *identifier = _FBTweakIdentifier(&entry); \
FBTweak *__inline_tweak = [collection tweakWithIdentifier:identifier]; \
\
return __inline_tweak; \
})())
#define _FBTweakInline(category_, collection_, name_, ...) _FBTweakDispatch(_FBTweakInlineWithoutRange, _FBTweakInlineWithRange, _FBTweakInlineWithPossible, __VA_ARGS__)(category_, collection_, name_, __VA_ARGS__)
#define _FBTweakValueInternal(tweak_, category_, collection_, name_, default_) \
((^{ \
/* returns a correctly typed version of the current tweak value */ \
FBTweakValue currentValue = tweak_.currentValue ?: tweak_.defaultValue; \
return _Generic(default_, \
float: [currentValue floatValue], \
const float: [currentValue floatValue], \
double: [currentValue doubleValue], \
const double: [currentValue doubleValue], \
short: [currentValue shortValue], \
const short: [currentValue shortValue], \
unsigned short: [currentValue unsignedShortValue], \
const unsigned short: [currentValue unsignedShortValue], \
int: [currentValue intValue], \
const int: [currentValue intValue], \
unsigned int: [currentValue unsignedIntValue], \
const unsigned int: [currentValue unsignedIntValue], \
long: [currentValue longValue], \
const long: [currentValue longValue], \
unsigned long: [currentValue unsignedLongValue], \
const unsigned long: [currentValue unsignedLongValue], \
long long: [currentValue longLongValue], \
const long long: [currentValue longLongValue], \
unsigned long long: [currentValue unsignedLongLongValue], \
const unsigned long long: [currentValue unsignedLongLongValue], \
BOOL: [currentValue boolValue], \
const BOOL: [currentValue boolValue], \
id: currentValue, \
const id: currentValue, \
/* assume char * as the default. */ \
/* constant strings are typed as char[N] */ \
/* and we can't enumerate all of those. */ \
/* luckily, we only need one fallback */ \
default: [currentValue UTF8String] \
); \
})())
#define _FBTweakValueWithoutRange(category_, collection_, name_, default_) \
((^{ \
FBTweak *__value_tweak = _FBTweakInlineWithoutRange(category_, collection_, name_, default_); \
return _FBTweakValueInternal(__value_tweak, category_, collection_, name_, default_); \
})())
#define _FBTweakValueWithRange(category_, collection_, name_, default_, min_, max_) \
((^{ \
FBTweak *__value_tweak = _FBTweakInlineWithRange(category_, collection_, name_, default_, min_, max_); \
return _FBTweakValueInternal(__value_tweak, category_, collection_, name_, default_); \
})())
#define _FBTweakValueWithPossible(category_, collection_, name_, default_, possible_) \
((^{ \
FBTweak *__value_tweak = _FBTweakInlineWithPossible(category_, collection_, name_, default_, possible_); \
return _FBTweakValueInternal(__value_tweak, category_, collection_, name_, default_); \
})())
#define _FBTweakValue(category_, collection_, name_, ...) _FBTweakDispatch(_FBTweakValueWithoutRange, _FBTweakValueWithRange, _FBTweakValueWithPossible, __VA_ARGS__)(category_, collection_, name_, __VA_ARGS__)
#define _FBTweakBindWithoutRange(object_, property_, category_, collection_, name_, default_) \
((^{ \
FBTweak *__bind_tweak = _FBTweakInlineWithoutRange(category_, collection_, name_, default_); \
_FBTweakBindInternal(object_, property_, category_, collection_, name_, default_, __bind_tweak); \
})())
#define _FBTweakBindWithRange(object_, property_, category_, collection_, name_, default_, min_, max_) \
((^{ \
FBTweak *__bind_tweak = _FBTweakInlineWithRange(category_, collection_, name_, default_, min_, max_); \
_FBTweakBindInternal(object_, property_, category_, collection_, name_, default_, __bind_tweak); \
})())
#define _FBTweakBindWithPossible(object_, property_, category_, collection_, name_, default_, possible_) \
((^{ \
FBTweak *__bind_tweak = _FBTweakInlineWithPossible(category_, collection_, name_, default_, possible_); \
_FBTweakBindInternal(object_, property_, category_, collection_, name_, default_, __bind_tweak); \
})())
#define _FBTweakBindInternal(object_, property_, category_, collection_, name_, default_, tweak_) \
((^{ \
object_.property_ = _FBTweakValueInternal(tweak_, category_, collection_, name_, default_); \
_FBTweakBindObserver *observer__ = [[_FBTweakBindObserver alloc] initWithTweak:tweak_ block:^(id object__) { \
__typeof__(object_) object___ = object__; \
object___.property_ = _FBTweakValueInternal(tweak_, category_, collection_, name_, default_); \
}]; \
[observer__ attachToObject:object_]; \
})())
#define _FBTweakBind(object_, property_, category_, collection_, name_, ...) _FBTweakDispatch(_FBTweakBindWithoutRange, _FBTweakBindWithRange, _FBTweakBindWithPossible, __VA_ARGS__)(object_, property_, category_, collection_, name_, __VA_ARGS__)
#define _FBTweakAction(category_, collection_, name_, ...) \
_FBTweakActionInternal(category_, collection_, name_, __COUNTER__, __VA_ARGS__)
#define _FBTweakActionInternal(category_, collection_, name_, suffix_, ...) \
/* store the tweak data in the binary at compile time. */ \
__attribute__((used)) static FBTweakLiteralString __FBTweakConcat(__fb_tweak_action_category_, suffix_) = category_; \
__attribute__((used)) static FBTweakLiteralString __FBTweakConcat(__fb_tweak_action_collection_, suffix_) = collection_; \
__attribute__((used)) static FBTweakLiteralString __FBTweakConcat(__fb_tweak_action_name_, suffix_) = name_; \
__attribute__((used)) static dispatch_block_t __FBTweakConcat(__fb_tweak_action_block_, suffix_) = __VA_ARGS__; \
__attribute__((used)) static char *__FBTweakConcat(__fb_tweak_action_encoding_, suffix_) = (char *)FBTweakEncodingAction; \
__attribute__((used)) __attribute__((section (FBTweakSegmentName "," FBTweakSectionName))) static fb_tweak_entry __FBTweakConcat(__fb_tweak_action_entry_, suffix_) = { \
&__FBTweakConcat(__fb_tweak_action_category_, suffix_), \
&__FBTweakConcat(__fb_tweak_action_collection_, suffix_), \
&__FBTweakConcat(__fb_tweak_action_name_, suffix_), \
&__FBTweakConcat(__fb_tweak_action_block_, suffix_), \
NULL, \
&__FBTweakConcat(__fb_tweak_action_encoding_, suffix_), \
}; \
#ifdef __cplusplus
}
#endif
#endif