main
 1//
 2// Licensed under the terms in License.txt
 3//
 4// Copyright 2010 Allen Ding. All rights reserved.
 5//
 6
 7#import "KWStringUtilities.h"
 8
 9#pragma mark -
10#pragma mark Checking for Case Separated Words
11
12BOOL KWStringHasWordPrefix(NSString *string, NSString *prefix) {
13    return [string isEqualToString:prefix] || KWStringHasStrictWordPrefix(string, prefix);
14}
15
16BOOL KWStringHasStrictWordPrefix(NSString *string, NSString *prefix) {
17    if (![string hasPrefix:prefix] || [string length] == [prefix length])
18        return NO;
19
20    unichar firstCharacterAfterPrefix = [string characterAtIndex:[prefix length]];
21    NSCharacterSet *uppercaseCharacterSet = [NSCharacterSet uppercaseLetterCharacterSet];
22    return [uppercaseCharacterSet characterIsMember:firstCharacterAfterPrefix];
23}
24
25BOOL KWStringHasWord(NSString *string, NSString *word) {
26    if (KWStringHasWordPrefix(string, word))
27        return YES;
28
29    NSCharacterSet *lowercaseCharacterSet = [NSCharacterSet lowercaseLetterCharacterSet];
30    NSCharacterSet *uppercaseCharacterSet = [NSCharacterSet uppercaseLetterCharacterSet];
31    NSRange searchRange = NSMakeRange(0, [string length]);
32
33    // Never match if word begins with a lowercase letter and was not a prefix.
34    if ([lowercaseCharacterSet characterIsMember:[word characterAtIndex:0]])
35        return NO;
36
37    while (1) {
38        if (searchRange.location >= [string length])
39            return NO;
40
41        NSRange range = [string rangeOfString:word options:0 range:searchRange];
42        searchRange.location = range.location + range.length;
43        searchRange.length = [string length] - searchRange.location;
44
45        if (range.location == NSNotFound)
46            return NO;
47
48        if (range.location > 0) {
49            unichar charBeforeRange = [string characterAtIndex:range.location - 1];
50
51
52            if (![lowercaseCharacterSet characterIsMember:charBeforeRange])
53                continue;
54        }
55
56        if (range.location + range.length < [string length]) {
57            unichar charAfterRange = [string characterAtIndex:range.location + range.length];
58
59            if (![uppercaseCharacterSet characterIsMember:charAfterRange])
60                continue;
61        }
62
63        return YES;
64    }
65}
66
67#pragma mark -
68#pragma mark Getting Type Encodings
69
70NSString *KWEncodingWithObjCTypes(const char *firstType, ...) {
71    if (firstType == nil)
72        return nil;
73
74    NSMutableString *encoding = [NSMutableString stringWithCapacity:8];
75    va_list argumentList;
76    va_start(argumentList, firstType);
77    const char *type = firstType;
78
79    do {
80        [encoding appendFormat:@"%s", type];
81        type = va_arg(argumentList, const char *);
82    } while (type != nil);
83
84    va_end(argumentList);
85    return encoding;
86}
87
88NSString *KWEncodingForVoidMethod(void) {
89    return KWEncodingWithObjCTypes(@encode(void), @encode(id), @encode(SEL), nil);
90}