17 #import "NIFoundationMethods.h"
19 #import "NIDebuggingTools.h"
20 #import <CommonCrypto/CommonDigest.h>
21 #import <objc/runtime.h>
23 #if !defined(__has_feature) || !__has_feature(objc_arc)
24 #error "Nimbus requires ARC support."
27 #pragma mark - NSInvocation
30 NSMethodSignature* sig = [targetObject methodSignatureForSelector:selector];
31 NSInvocation* inv = [NSInvocation invocationWithMethodSignature:sig];
32 [inv setTarget:targetObject];
33 [inv setSelector:selector];
38 Method method = class_getInstanceMethod(targetClass, selector);
39 struct objc_method_description* desc = method_getDescription(method);
40 if (desc == NULL || desc->name == NULL)
43 NSMethodSignature* sig = [NSMethodSignature signatureWithObjCTypes:desc->types];
44 NSInvocation* inv = [NSInvocation invocationWithMethodSignature:sig];
45 [inv setSelector:selector];
52 return CGRectMake(rect.origin.x, rect.origin.y, rect.size.width - dx, rect.size.height - dy);
56 return CGRectMake(rect.origin.x, rect.origin.y, rect.size.width + dx, rect.size.height + dy);
64 return CGRectMake(rect.origin.x - outsets.left,
65 rect.origin.y - outsets.top,
66 rect.size.width + outsets.left + outsets.right,
67 rect.size.height + outsets.top + outsets.bottom);
70 CGFloat
NICenterX(CGSize containerSize, CGSize size) {
74 CGFloat
NICenterY(CGSize containerSize, CGSize size) {
80 CGSize containerViewSize = containerView.bounds.size;
81 CGSize viewSize = viewToCenter.frame.size;
82 origin.x =
NICenterX(containerViewSize, viewSize);
83 origin.y =
NICenterY(containerViewSize, viewSize);
84 return CGRectMake(origin.x, origin.y, viewSize.width, viewSize.height);
88 if (
string.length == 0) {
92 CGFloat lineHeight = font.lineHeight;
93 CGSize size = CGSizeZero;
95 if (numberOfLines == 1) {
96 size = [string sizeWithFont:font forWidth:constrainedToSize.width lineBreakMode:lineBreakMode];
99 size = [string sizeWithFont:font constrainedToSize:constrainedToSize lineBreakMode:lineBreakMode];
100 if (numberOfLines > 0) {
101 size.height = MIN(size.height, numberOfLines * lineHeight);
108 #pragma mark - NSRange
113 NIDASSERT(range.location >= 0 && range.location <= NSIntegerMax);
114 NIDASSERT(range.length >= 0 && range.length <= NSIntegerMax);
115 return NSMakeRange(range.location, range.length);
118 #pragma mark - NSData
121 unsigned char result[CC_MD5_DIGEST_LENGTH];
122 bzero(result,
sizeof(result));
123 CC_MD5_CTX md5Context;
124 CC_MD5_Init(&md5Context);
125 size_t bytesHashed = 0;
126 while (bytesHashed < [data length]) {
127 CC_LONG updateSize = 1024 * 1024;
128 if (([data length] - bytesHashed) < (
size_t)updateSize) {
129 updateSize = (CC_LONG)([data length] - bytesHashed);
131 CC_MD5_Update(&md5Context, (
char *)[data bytes] + bytesHashed, updateSize);
132 bytesHashed += updateSize;
134 CC_MD5_Final(result, &md5Context);
136 return [NSString stringWithFormat:
137 @"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
138 result[0], result[1], result[2], result[3], result[4], result[5], result[6], result[7],
139 result[8], result[9], result[10], result[11], result[12], result[13], result[14],
145 unsigned char result[CC_SHA1_DIGEST_LENGTH];
146 bzero(result,
sizeof(result));
147 CC_SHA1_CTX sha1Context;
148 CC_SHA1_Init(&sha1Context);
149 size_t bytesHashed = 0;
150 while (bytesHashed < [data length]) {
151 CC_LONG updateSize = 1024 * 1024;
152 if (([data length] - bytesHashed) < (
size_t)updateSize) {
153 updateSize = (CC_LONG)([data length] - bytesHashed);
155 CC_SHA1_Update(&sha1Context, (
char *)[data bytes] + bytesHashed, updateSize);
156 bytesHashed += updateSize;
158 CC_SHA1_Final(result, &sha1Context);
160 return [NSString stringWithFormat:
161 @"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
162 result[0], result[1], result[2], result[3], result[4], result[5], result[6], result[7],
163 result[8], result[9], result[10], result[11], result[12], result[13], result[14],
164 result[15], result[16], result[17], result[18], result[19]
168 #pragma mark - NSString
179 NSCharacterSet* notWhitespaceAndNewlines = [[NSCharacterSet whitespaceAndNewlineCharacterSet] invertedSet];
180 return [string isKindOfClass:[NSString class]] && [string rangeOfCharacterFromSet:notWhitespaceAndNewlines].length == 0;
184 NSArray *oneComponents = [string1 componentsSeparatedByString:@"a"];
185 NSArray *twoComponents = [string2 componentsSeparatedByString:@"a"];
188 NSString *oneMain = [oneComponents objectAtIndex:0];
189 NSString *twoMain = [twoComponents objectAtIndex:0];
192 NSComparisonResult mainDiff;
193 if ((mainDiff = [oneMain compare:twoMain]) != NSOrderedSame) {
199 if ([oneComponents count] < [twoComponents count]) {
200 return NSOrderedDescending;
202 }
else if ([oneComponents count] > [twoComponents count]) {
203 return NSOrderedAscending;
205 }
else if ([oneComponents count] == 1) {
207 return NSOrderedSame;
212 NSNumber *oneAlpha = [NSNumber numberWithInt:[[oneComponents objectAtIndex:1] intValue]];
213 NSNumber *twoAlpha = [NSNumber numberWithInt:[[twoComponents objectAtIndex:1] intValue]];
214 return [oneAlpha compare:twoAlpha];
218 NSCharacterSet* delimiterSet = [NSCharacterSet characterSetWithCharactersInString:@"&;"];
219 NSMutableDictionary* pairs = [NSMutableDictionary dictionary];
220 NSScanner* scanner = [[NSScanner alloc] initWithString:string];
222 while (![scanner isAtEnd]) {
223 NSString* pairString = nil;
224 [scanner scanUpToCharactersFromSet:delimiterSet intoString:&pairString];
225 [scanner scanCharactersFromSet:delimiterSet intoString:NULL];
227 NSArray* kvPair = [pairString componentsSeparatedByString:@"="];
228 if (kvPair.count == 1 || kvPair.count == 2) {
229 NSString* key = [kvPair[0] stringByReplacingPercentEscapesUsingEncoding:encoding];
231 NSMutableArray* values = pairs[key];
233 values = [NSMutableArray array];
237 if (kvPair.count == 1) {
238 [values addObject:[NSNull null]];
240 }
else if (kvPair.count == 2) {
241 NSString* value = [kvPair[1] stringByReplacingPercentEscapesUsingEncoding:encoding];
242 [values addObject:value];
250 CFStringRef buffer = CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
251 (__bridge CFStringRef)parameter,
253 (__bridge CFStringRef)
@"!*'();:@&=+$,/?%#[]",
254 kCFStringEncodingUTF8);
256 NSString* result = [NSString stringWithString:(__bridge NSString *)buffer];
262 NSMutableArray* pairs = [NSMutableArray array];
263 for (NSString* key in [query keyEnumerator]) {
265 NSString* pair = [NSString stringWithFormat:@"%@=%@", key, value];
266 [pairs addObject:pair];
269 NSString* params = [pairs componentsJoinedByString:@"&"];
270 if ([
string rangeOfString:
@"?"].location == NSNotFound) {
271 return [string stringByAppendingFormat:@"?%@", params];
274 return [string stringByAppendingFormat:@"&%@", params];
278 #pragma mark - General Purpose
281 CGFloat
boundf(CGFloat value, CGFloat min, CGFloat max) {
286 NSInteger
boundi(NSInteger value, NSInteger min, NSInteger max) {
290 CGFloat
NIBoundf(CGFloat value, CGFloat min, CGFloat max) {
294 CGFloat bounded = value;
304 NSInteger
NIBoundi(NSInteger value, NSInteger min, NSInteger max) {
308 NSInteger bounded = value;
NSRange NIMakeNSRangeFromCFRange(CFRange range)
Create an NSRange object from a CFRange object.
NSDictionary * NIQueryDictionaryFromStringUsingEncoding(NSString *string, NSStringEncoding encoding)
Parses a URL query string into a dictionary where the values are arrays.
NSString * NIMD5HashFromData(NSData *data)
Calculates an md5 hash of the data using CC_MD5.
CGRect NIRectContract(CGRect rect, CGFloat dx, CGFloat dy)
Modifies only the right and bottom edges of a CGRect.
CG_INLINE CGFloat NICGFloatFloor(CGFloat x)
floor()/floorf() sized for CGFloat
NSString * NIMD5HashFromString(NSString *string)
Calculates an md5 hash of the string using CC_MD5.
BOOL NIIsStringWithWhitespaceAndNewlines(NSString *string)
Returns a Boolean value indicating whether the string is a NSString object that contains only whitesp...
CGRect NIRectExpand(CGRect rect, CGFloat dx, CGFloat dy)
Modifies only the right and bottom edges of a CGRect.
CGFloat boundf(CGFloat value, CGFloat min, CGFloat max)
Deprecated method.
NSInteger boundi(NSInteger value, NSInteger min, NSInteger max)
Deprecated method.
NSString * NISHA1HashFromData(NSData *data)
Calculates a sha1 hash of the data using CC_SHA1.
NSString * NISHA1HashFromString(NSString *string)
Calculates a sha1 hash of the string using CC_SHA1.
CGSize NISizeOfStringWithLabelProperties(NSString *string, CGSize constrainedToSize, UIFont *font, NSLineBreakMode lineBreakMode, NSInteger numberOfLines)
Returns the size of the string with given UILabel properties.
CGFloat NIBoundf(CGFloat value, CGFloat min, CGFloat max)
Bounds a given value within the min and max values.
NSInteger NIBoundi(NSInteger value, NSInteger min, NSInteger max)
Bounds a given value within the min and max values.
NSComparisonResult NICompareVersionStrings(NSString *string1, NSString *string2)
Compares two strings expressing software versions.
CGRect NIRectShift(CGRect rect, CGFloat dx, CGFloat dy)
Modifies only the top and left edges of a CGRect.
NSInvocation * NIInvocationWithClassTarget(Class targetClass, SEL selector)
Construct an NSInvocation for a class method given a class object and a selector. ...
CGFloat NICenterX(CGSize containerSize, CGSize size)
Returns the x position that will center size within containerSize.
CGFloat NICenterY(CGSize containerSize, CGSize size)
Returns the y position that will center size within containerSize.
NSString * NIStringByAddingQueryDictionaryToString(NSString *string, NSDictionary *query)
Appends a dictionary of query parameters to a string, adding the ? character if necessary.
NSInvocation * NIInvocationWithInstanceTarget(NSObject *targetObject, SEL selector)
Construct an NSInvocation with an instance of an object and a selector.
CGRect NIFrameOfCenteredViewWithinView(UIView *viewToCenter, UIView *containerView)
Returns a rect that will center viewToCenter within containerView.
NSString * NIStringByAddingPercentEscapesForURLParameterString(NSString *parameter)
Returns a string that has been escaped for use as a URL parameter.
CGRect NIEdgeInsetsOutsetRect(CGRect rect, UIEdgeInsets outsets)
Inverse of UIEdgeInsetsInsetRect.