Commit 95828800 by Brent Gulanowski

Merge pull request #118 from Shopify/task/migrate-cocoa-additions

Update extensions to Cocoa Foundation classes.
parents 01d26e97 e2fbdf60
//
// BUYModelArrayAdditionsTests.m
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import <XCTest/XCTest.h>
#import "NSArray+BUYAdditions.h"
@interface BUYArrayAdditionsTests : XCTestCase
@end
@implementation BUYArrayAdditionsTests
- (void)testNilMap {
NSArray *empty = @[];
XCTAssertEqualObjects([empty buy_map:nil], empty, @"buy_map failed");
NSArray *array = @[@1, @2];
XCTAssertEqualObjects([array buy_map:nil], empty, @"buy_map failed");
}
- (void)testMap {
NSArray *expected = @[@2, @4, @6];
NSArray *actual = [@[@1, @2, @3] buy_map:^id(NSNumber *number) {
return @([number unsignedIntegerValue] * 2);
}];
XCTAssertEqualObjects(actual, expected, @"map count was incorrect");
}
- (void)testReverse {
NSArray *expected = @[@3, @2, @1];
NSArray *actual = [@[@1, @2, @3] buy_reversedArray];
XCTAssertEqualObjects(actual, expected, @"reversed array was incorrect");
}
- (void)testMutableReverse {
NSArray *array = @[@1, @2, @3];
NSArray *expected = @[@3, @2, @1];
NSMutableArray *actual = [array mutableCopy];
[actual buy_reverse];
XCTAssertEqualObjects(actual, expected, @"reversed array was incorrect");
}
- (void)testTail {
NSArray *array = @[];
NSArray *expected = @[];
XCTAssertEqualObjects(array.buy_tail, expected, @"tail array incorrect");
array = @[@1, @2, @3];
expected = @[@2, @3];
XCTAssertEqualObjects(array.buy_tail, expected, @"tail array incorrect");
}
- (void)testNSObjectToArray {
id value = @"hello";
id expected = @[@"hello"];
id actual = [value buy_array];
XCTAssertEqualObjects(actual, expected, @"array form incorrect");
expected = value;
actual = [NSObject buy_convertArray:@[value]];
XCTAssertEqualObjects(actual, expected, @"unwrapped array was incorrect");
}
- (void)testNSArrayToArray {
id value = @[@1, @2];
id expected = @[@1, @2];
id actual = [value buy_array];
XCTAssertEqualObjects(actual, expected, @"array form incorrect");
expected = value;
actual = [NSArray buy_convertArray:@[@1, @2]];
XCTAssertEqualObjects(actual, expected, @"unwrapped array was incorrect");
}
- (void)testNSSetToArray {
id value = [NSSet setWithArray:@[@1, @2]];
id expected = @[@1, @2];
id actual = [value buy_array];
XCTAssertEqualObjects(actual, expected, @"array form incorrect");
expected = value;
actual = [NSSet buy_convertArray:@[@1, @2]];
XCTAssertEqualObjects(actual, expected, @"unwrapped array was incorrect");
}
- (void)testNSOrderedSetToArray {
id value = [NSOrderedSet orderedSetWithArray:@[@1, @2]];
id expected = @[@1, @2];
id actual = [value buy_array];
XCTAssertEqualObjects(actual, expected, @"array form incorrect");
expected = value;
actual = [NSOrderedSet buy_convertArray:@[@1, @2]];
XCTAssertEqualObjects(actual, expected, @"unwrapped array was incorrect");
}
@end
//
// BUYModelDictionaryAdditionsTests.m
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import <XCTest/XCTest.h>
#import "NSDictionary+BUYAdditions.h"
@interface BUYDictionaryAdditionsTests : XCTestCase
@end
@implementation BUYDictionaryAdditionsTests
- (NSDictionary *)englishToFrench
{
return @{
@"one": @"un",
@"two": @"deux",
@"three": @"trois",
@"four": @"quatre",
};
}
- (NSDictionary *)stringsToNumbers
{
return @{
@"one": @1,
@"two": @2,
@"three": @3,
@"four": @4,
@"five": @5,
};
}
- (void)testReverseDictionary {
NSDictionary *expected = @{
@"un": @"one",
@"deux": @"two",
@"trois": @"three",
@"quatre": @"four",
};
XCTAssertEqualObjects([self englishToFrench].buy_reverseDictionary, expected, @"reverse dictionary was incorrect");
}
- (void)testKeyMapping
{
NSDictionary *JSON = [self stringsToNumbers];
NSDictionary *expected = @{
@"un": @1,
@"deux": @2,
@"trois": @3,
@"quatre": @4,
@"five":@5
};
NSDictionary *mapping = [self englishToFrench];
NSDictionary *actual = [JSON buy_dictionaryByMappingKeysWithBlock:^(NSString *key) {
return mapping[key];
}];
XCTAssertEqualObjects(actual, expected, @"converted dictionary was incorrect");
}
- (void)testValueMapping
{
NSDictionary *JSON = [[self englishToFrench] buy_reverseDictionary];
NSDictionary *mapping = [self stringsToNumbers];
NSDictionary *expected = @{
@"un": @1,
@"deux": @2,
@"trois": @3,
@"quatre": @4,
};
NSDictionary *actual = [JSON buy_dictionaryByMappingValuesWithBlock:^(id value) {
return mapping[value];
}];
XCTAssertEqualObjects(actual, expected, @"converted dictionary was incorrect");
}
@end
//
// BUYExceptionAdditionsTests.m
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import <XCTest/XCTest.h>
#import "NSException+BUYAdditions.h"
@interface BUYExceptionAdditionsTests : XCTestCase
@end
@implementation BUYExceptionAdditionsTests
- (void)abstractMethod
{
@throw BUYAbstractMethod();
}
- (void)testAbstractMethodException
{
@try {
[self abstractMethod];
XCTFail();
}
@catch (NSException *exception) {
XCTAssertNotNil(exception);
}
}
@end
//
// BUYFontAdditionsTests.m
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import <XCTest/XCTest.h>
#import "UIFont+BUYAdditions.h"
@interface BUYFontAdditionsTests : XCTestCase
@end
@implementation BUYFontAdditionsTests
- (void)testIncreasedFontSize
{
static CGFloat const increase = 2.0;
UIFont *font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody];
CGFloat newSize = font.pointSize + increase;
NSMutableDictionary *attributes = [font.fontDescriptor.fontAttributes mutableCopy];
attributes[UIFontDescriptorSizeAttribute] = @(newSize);
UIFont *expected = [UIFont fontWithDescriptor:[UIFontDescriptor fontDescriptorWithFontAttributes:attributes] size:newSize];
UIFont *actual = [UIFont preferredFontForTextStyle:UIFontTextStyleBody increasedPointSize:increase];
XCTAssertEqualObjects(actual, expected);
}
@end
//
// BUYModelRegularExpressionAdditionTests.m
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import <XCTest/XCTest.h>
#import "NSRegularExpression+BUYAdditions.h"
@interface BUYRegularExpressionAdditionsTests : XCTestCase
@end
@implementation BUYRegularExpressionAdditionsTests
- (void)testMatchesInEmptyString {
NSArray *expected = @[];
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"hello" options:0 error:NULL];
NSArray *actual = [regex buy_matchesInString:@""];
XCTAssertEqualObjects(actual, expected, @"matches array was incorrect");
}
- (void)testSingleMatch {
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"hello" options:0 error:NULL];
NSArray *matches = [regex buy_matchesInString:@"_hello_"];
XCTAssertEqual(matches.count, (NSUInteger)1, @"number of matches incorrect");
NSRange expected = NSMakeRange(1, 5);
NSRange actual = [matches.firstObject range];
XCTAssertEqual(actual.location, expected.location, @"location of match was incorrect");
XCTAssertEqual(actual.length, expected.length, @"length of match was incorrect");
}
- (void)testMultipleMatches {
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"hello" options:0 error:NULL];
NSArray *matches = [regex buy_matchesInString:@"_hello_hello___hellhello234234"];
XCTAssertEqual(matches.count, (NSUInteger)3, @"number of matches incorrect");
NSRange expected[3] = {NSMakeRange(1, 5), NSMakeRange(7, 5), NSMakeRange(19, 5)};
for (NSUInteger i = 0; i < 3; ++i) {
NSRange actual = [matches[i] range];
XCTAssertTrue(NSEqualRanges(actual, expected[i]), @"ranges did not match");
}
}
- (void)testFirstMatch {
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"hello" options:0 error:NULL];
NSTextCheckingResult *match = [regex buy_firstMatchInString:@"hello_hello"];
NSRange expected = NSMakeRange(0, 5);
NSRange actual = [match range];
XCTAssertTrue(NSEqualRanges(actual, expected), @"ranges did not match");
}
@end
//
// BUYModelStringAdditionsTests.m
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import <XCTest/XCTest.h>
#import "NSString+BUYAdditions.h"
@interface BUYStringAdditionsTests : XCTestCase
@end
static NSString * const lettersAndNumbers = @"abcdefghijklmnopqrstuvwxyz1234567890";
static NSString * const testMatchingString = @"stringstrongstingstringring";
static NSString * const matchPattern = @"str?\\w?ng";
static NSString * const camelCaseString = @"camelCaseString";
static NSString * const camelCaseSTRING = @"camelCaseSTRING";
static NSString * const camelCASEString = @"camelCASEString";
static NSString * const CAMELCaseString = @"CAMELCaseString";
@implementation BUYStringAdditionsTests {
NSArray *_oldAcronyms;
}
- (void)setUp
{
[super setUp];
_oldAcronyms = [NSString buy_acronymStrings];
}
- (void)tearDown
{
[super tearDown];
[NSString buy_setAcronymStrings:_oldAcronyms];
_oldAcronyms = nil;
}
- (void)testReversedString {
NSString *expected = @"0987654321zyxwvutsrqponmlkjihgfedcba";
NSString *actual = [lettersAndNumbers buy_reversedString];
XCTAssertEqualObjects(actual, expected, @"reversed string was incorrect");
}
- (void)testMatchesForRegularExpression {
NSArray *expected = @[@"string", @"strong", @"sting", @"string"];
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:matchPattern options:0 error:NULL];
NSArray *actual = [testMatchingString buy_matchesForRegularExpression:regex];
XCTAssertEqualObjects(actual, expected, @"patterns did not match");
}
- (void)testFirstMatchForRegularExpression {
NSString *expected = @"string";
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:matchPattern options:0 error:NULL];
NSString *actual = [testMatchingString buy_firstMatchForRegularExpression:regex];
XCTAssertEqualObjects(actual, expected, @"patterns did not match");
}
- (void)testMatchesForPattern {
NSArray *expected = @[@"string", @"strong", @"sting", @"string"];
NSArray *actual = [testMatchingString buy_matchesForPattern:matchPattern];
XCTAssertEqualObjects(actual, expected, @"patterns did not match");
}
- (void)testFirstMatchForPattern {
NSString *expected = @"string";
NSString *actual = [testMatchingString buy_firstMatchForPattern:matchPattern];
XCTAssertEqualObjects(actual, expected, @"patterns did not match");
}
- (void)testCamelCaseTokens {
NSArray *expected = @[@"camel", @"Case", @"String"];
NSArray *actual = [camelCaseString buy_camelCaseTokens];
XCTAssertEqualObjects(actual, expected, @"tokens were incorrect");
}
- (void)testCamelCaseALLCAPSTokens {
NSArray *expected = @[@"camel", @"Case", @"STRING"];
NSArray *actual = [camelCaseSTRING buy_camelCaseTokens];
XCTAssertEqualObjects(actual, expected, @"tokens were incorrect");
expected = @[@"camel", @"CASE", @"String"];
actual = [camelCASEString buy_camelCaseTokens];
XCTAssertEqualObjects(actual, expected, @"tokens were incorrect");
expected = @[@"CAMEL", @"Case", @"String"];
actual = [CAMELCaseString buy_camelCaseTokens];
XCTAssertEqualObjects(actual, expected, @"tokens were incorrect");
}
- (void)testSnakeCaseString {
NSString *expected = @"camel_case_string";
NSString *actual = [camelCaseString buy_snakeCaseString];
XCTAssertEqualObjects(actual, expected, @"snake case string was incorrect");
actual = [camelCaseSTRING buy_snakeCaseString];
XCTAssertEqualObjects(actual, expected, @"snake case string was incorrect");
actual = [camelCASEString buy_snakeCaseString];
XCTAssertEqualObjects(actual, expected, @"snake case string was incorrect");
actual = [CAMELCaseString buy_snakeCaseString];
XCTAssertEqualObjects(actual, expected, @"snake case string was incorrect");
}
- (void)testCamelCaseString {
NSString *expected = @"snakeCaseString";
NSString *actual = [@"snake_case_string" buy_camelCaseString];
XCTAssertEqualObjects(actual, expected, @"camel case string was incorrect");
}
- (void)testAcronyms {
NSArray *expected = @[ @"url"];
NSArray *actual = [NSString buy_acronymStrings];
XCTAssertEqualObjects(actual, expected, @"Default acronyms not correct");
NSArray *acronyms = @[ @"hello" ];
[NSString buy_setAcronymStrings:acronyms];
expected = acronyms;
actual = [NSString buy_acronymStrings];
XCTAssertEqualObjects(actual, expected, @"Custom acronyms not correct");
}
- (void)testCamelCaseStringWithAcronyms {
NSString *expected = @"URLString";
NSString *actual = [@"url_string" buy_camelCaseString];
XCTAssertEqualObjects(actual, expected, @"camel case string was incorrect");
expected = @"stringWithURL";
actual = [@"string_with_url" buy_camelCaseString];
XCTAssertEqualObjects(actual, expected, @"camel case string was incorrect");
[NSString buy_setAcronymStrings:@[@"awol", @"GDP", @"sdk"]];
expected = @"goneAWOL";
actual = [@"gone_awol" buy_camelCaseString];
XCTAssertEqualObjects(actual, expected, @"camel case string was incorrect");
expected = @"SDKTypes";
actual = [@"sdk_types" buy_camelCaseString];
XCTAssertEqualObjects(actual, expected, @"camel case string was incorrect");
expected = @"GDPCanada";
actual = [@"gdp_canada" buy_camelCaseString];
XCTAssertEqualObjects(actual, expected, @"camel case string was incorrect");
}
- (void)testReplacingFileName
{
NSString *path = @"/path/to/file.txt";
NSString *expected = @"/path/to/other_file.txt";
NSString *actual = [path buy_stringByReplacingBaseFileName:@"other_file"];
XCTAssertEqualObjects(actual, expected);
}
- (void)testReplacingDirectory
{
NSString *path = @"/path/to/file.txt";
NSString *expected = @"/directory_2/file.txt";
NSString *actual = [path buy_stringByReplacingDirectory:@"/directory_2"];
XCTAssertEqualObjects(actual, expected);
}
- (void)testStrippingHTML
{
NSString *rawHTML = @"<!DOCTYPE html>\
<html>\
<body>\
\
<h1>My First Heading</h1>\
\
<p>My first paragraph.</p>\
\
</body>\
</html>";
NSString *expected = @"My First Heading\nMy first paragraph.\n";
NSString *actual = [rawHTML buy_stringByStrippingHTML];
XCTAssertEqualObjects(actual, expected);
}
- (void)testAttributeStringWithLineSpacing
{
NSString *string = @"Hello, world";
NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init];
style.lineSpacing = 2.0;
style.alignment = NSTextAlignmentCenter;
NSAttributedString *expected = [[NSAttributedString alloc] initWithString:string attributes:@{ NSParagraphStyleAttributeName : style }];
NSAttributedString *actual = [string buy_attributedStringWithLineSpacing:2.0 textAlignment:NSTextAlignmentCenter];
XCTAssertEqualObjects(actual, expected);
}
- (void)testTrim
{
NSString *string = @" \t\n Hello \t\n";
NSString *expected = @"Hello";
NSString *actual = [string buy_trim];
XCTAssertEqualObjects(actual, expected);
}
@end
//
// BUYURLAdditionsTests.m
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import <XCTest/XCTest.h>
#import "NSURL+BUYAdditions.h"
@interface BUYURLAdditionsTests : XCTestCase
@end
@implementation BUYURLAdditionsTests
- (void)testAppendBasenameSuffix
{
NSString *string = @"http://shopify.com/file.txt";
NSURL *url = [NSURL URLWithString:string];
NSURL *expected = [NSURL URLWithString:@"http://shopify.com/file_big.txt"];
NSURL *actual = [url buy_URLByAppendingFileBaseNameSuffix:@"_big"];
XCTAssertEqualObjects(actual, expected);
}
@end
//
// NSArray+BUYAdditions.h
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import <Foundation/Foundation.h>
typedef id (^BUYObjectMap) (id);
@interface NSArray (BUYAdditions)
/**
* Return all but the first object.
*/
@property (nonatomic, readonly, getter=buy_tail) NSArray *tail;
/**
* Return a copy of the array with objects in in reverse order.
*/
@property (nonatomic, readonly, getter=buy_reversedArray) NSArray *reversedArray;
- (NSArray *)buy_map:(BUYObjectMap)block;
@end
@interface NSMutableArray (BUYAdditions)
/**
* Reverse the order of the objects in place.
*/
- (void)buy_reverse;
@end
@interface NSObject (BUYModelArrayCreating)
/**
* Returns an array form of the object.
* Collections are converted to an array. Other objects are wrapped in an array.
*/
- (NSArray *)buy_array;
/**
* Returns an object initialized with the given array.
* Collections convert the array to themselves. Other objects unwrap the array.
*/
+ (instancetype)buy_convertArray:(NSArray *)array;
@end
//
// NSArray+BUYAdditions.m
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import "NSArray+BUYAdditions.h"
@implementation NSArray (BUYAdditions)
- (NSArray *)buy_reversedArray
{
NSMutableArray *array = [self mutableCopy];
[array buy_reverse];
return array;
}
- (NSArray *)buy_map:(BUYObjectMap)block
{
if (block == nil) {
return @[];
}
NSMutableArray *array = [NSMutableArray array];
[self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
[array addObject:block(obj)];
}];
return array;
}
- (NSArray *)buy_tail
{
if (self.count > 0) {
return [self subarrayWithRange:NSMakeRange(1, self.count - 1)];
}
else {
return @[];
}
}
@end
#pragma mark -
@implementation NSMutableArray (BUYAdditions)
- (void)buy_reverse
{
const NSUInteger count = self.count;
const NSUInteger mid = count/2;
for (NSUInteger i=0; i<mid; ++i) {
const NSUInteger opposite = count-i-1;
id temp = self[i];
[self replaceObjectAtIndex:i withObject:self[opposite]];
[self replaceObjectAtIndex:opposite withObject:temp];
}
}
@end
@implementation NSObject (BUYModelArrayCreating)
- (NSArray *)buy_array
{
return @[[self copy]];
}
+ (instancetype)buy_convertArray:(NSArray *)array
{
return array.firstObject;
}
@end
@implementation NSArray (BUYModelArrayCreating)
- (NSArray *)buy_array
{
return self;
}
+ (instancetype)buy_convertArray:(NSArray *)array
{
return [array copy];
}
@end
@implementation NSSet (BUYModelArrayCreating)
- (NSArray *)buy_array
{
return [self allObjects];
}
+ (instancetype)buy_convertArray:(NSArray *)array
{
return [NSSet setWithArray:array];
}
@end
@implementation NSOrderedSet (BUYModelArrayCreating)
- (NSArray *)buy_array
{
return [self array];
}
+ (instancetype)buy_convertArray:(NSArray *)array
{
return [NSOrderedSet orderedSetWithArray:array];
}
@end
......@@ -29,15 +29,6 @@
@interface NSDecimalNumber (BUYAdditions)
/**
* Converts a string into an NSDecimalNumber or zero (if nil or not a number)
*
* @param string The string to convert
*
* @return NSDecimalNumber from a string
*/
+ (NSDecimalNumber*)buy_decimalNumberOrZeroWithString:(NSString*)string;
/**
* Converts a JSON value to an NSDecimalNumber
*
* @param valueFromJSON The value to convert
......
......@@ -26,20 +26,11 @@
#import "NSDecimalNumber+BUYAdditions.h"
@implementation NSDecimalNumber (BUYAdditions)
@interface NSObject (BUYDecimalCreating)
@property (nonatomic, readonly, getter=buy_decimalNumber) NSDecimalNumber *decimalNumber;
@end
+ (NSDecimalNumber*)buy_decimalNumberOrZeroWithString:(NSString*)string
{
NSDecimalNumber *decimalNumber = nil;
if (string) {
decimalNumber = [NSDecimalNumber decimalNumberWithString:string];
}
if (decimalNumber == nil || decimalNumber == [NSDecimalNumber notANumber]) {
decimalNumber = [NSDecimalNumber zero];
}
return decimalNumber;
}
@implementation NSDecimalNumber (BUYAdditions)
+ (NSDecimalNumber*)buy_decimalNumberFromJSON:(id)valueFromJSON
{
......@@ -49,22 +40,8 @@
numberHandler = [[NSDecimalNumberHandler alloc] initWithRoundingMode:NSRoundBankers scale:12 raiseOnExactness:NO raiseOnOverflow:NO raiseOnUnderflow:NO raiseOnDivideByZero:NO];
});
NSDecimalNumber *decimalNumber = nil;
if (valueFromJSON == nil || [valueFromJSON isKindOfClass:[NSNull class]]) {
decimalNumber = nil;
}
else if ([valueFromJSON isKindOfClass:[NSString class]]) {
decimalNumber = [NSDecimalNumber buy_decimalNumberOrZeroWithString:valueFromJSON];
}
else if ([valueFromJSON isKindOfClass:[NSDecimalNumber class]]) {
decimalNumber = valueFromJSON;
}
else if ([valueFromJSON isKindOfClass:[NSNumber class]]) {
NSDecimal decimal = [(NSNumber*)valueFromJSON decimalValue];
decimalNumber = [NSDecimalNumber decimalNumberWithDecimal:decimal];
}
else {
decimalNumber = nil;
NSDecimalNumber *decimalNumber = [valueFromJSON buy_decimalNumber];
if (decimalNumber == nil) {
NSLog(@"Could not create decimal value: %@", valueFromJSON);
}
......@@ -77,3 +54,41 @@
}
@end
#pragma mark -
@implementation NSObject (BUYDecimalCreating)
- (NSDecimalNumber *)buy_decimalNumber
{
return nil;
}
@end
@implementation NSString (BUYDecimalCreating)
- (NSDecimalNumber *)buy_decimalNumber
{
return [NSDecimalNumber decimalNumberWithString:self];
}
@end
@implementation NSNumber (BUYDecimalCreating)
- (NSDecimalNumber *)buy_decimalNumber
{
return [NSDecimalNumber decimalNumberWithDecimal:[self decimalValue]];
}
@end
@implementation NSDecimalNumber (BUYDecimalCreating)
- (NSDecimalNumber *)buy_decimalNumber
{
return self;
}
@end
//
// NSDictionary+Additions.h
//
// NSDictionary+BUYAdditions.h
// Mobile Buy SDK
//
// Created by Shopify.
......@@ -26,8 +25,27 @@
//
#import <Foundation/Foundation.h>
#import "BUYSerializable.h"
#import "NSArray+BUYAdditions.h"
typedef NSString * (^BUYStringMap) (NSString *);
@interface NSDictionary (BUYAdditions) <BUYSerializable>
/**
* Return a new dictionary where the objects are used as keys, and vice versa.
*/
- (NSDictionary<NSString *, NSString *> *)buy_reverseDictionary;
@interface NSDictionary (Additions)
/**
* Return a new dictionary, replacing existing keys with new keys provided by the map block.
*/
- (NSDictionary *)buy_dictionaryByMappingKeysWithBlock:(BUYStringMap)map;
/**
* Return a new dictionary, replacing existing values with new values provided by the map block.
*/
- (NSDictionary *)buy_dictionaryByMappingValuesWithBlock:(BUYObjectMap)map;
/**
* Alernative to objectForKey, where NSNull is replaced with nil
......
//
// NSDictionary+BUYAdditions.m
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import "NSDictionary+BUYAdditions.h"
#import "NSString+BUYAdditions.h"
@implementation NSDictionary (BUYAdditions)
- (NSDictionary<NSString *, NSString *> *)buy_reverseDictionary
{
return [NSDictionary dictionaryWithObjects:self.allKeys forKeys:self.allValues];
}
- (NSDictionary *)buy_dictionaryByMappingKeysWithBlock:(BUYStringMap)map
{
NSMutableDictionary *result = [NSMutableDictionary dictionary];
[self enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
result[(map(key) ?: key)] = self[key];
}];
return result;
}
- (NSDictionary *)buy_dictionaryByMappingValuesWithBlock:(BUYObjectMap)map
{
NSMutableDictionary *result = [NSMutableDictionary dictionary];
[self enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
id newValue = map(self[key]);
result[key] = newValue;
}];
return result;
}
- (id)buy_objectForKey:(NSString *)key
{
return ([self[key] isKindOfClass:[NSNull class]]) ? nil : self[key];
}
- (NSDictionary *)jsonDictionaryForCheckout
{
return self;
}
@end
//
// NSException+BUYAdditions.h
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import <Foundation/Foundation.h>
/**
* A macro meant to be used with `@throw` to make it easier to raise the given exception type.
*/
#define BUYAbstractMethod() [NSException buy_abstractMethodExceptionForSelector:_cmd class:[self class]]
@interface NSException (BUYAdditions)
/**
* Return an exception suitable for raising in a method that requires subclasses to override it.
*/
+ (instancetype)buy_abstractMethodExceptionForSelector:(SEL)selector class:(Class)klass;
@end
//
// NSDictionary+Additions.m
//
// NSException+BUYAdditions.m
// Mobile Buy SDK
//
// Created by Shopify.
......@@ -25,13 +24,14 @@
// THE SOFTWARE.
//
#import "NSDictionary+Additions.h"
#import "NSException+BUYAdditions.h"
@implementation NSDictionary (Additions)
@implementation NSException (BUYAdditions)
- (id)buy_objectForKey:(NSString *)key
+ (instancetype)buy_abstractMethodExceptionForSelector:(SEL)selector class:(Class)class
{
return ([self[key] isKindOfClass:[NSNull class]]) ? nil : self[key];
NSString *reason = [NSString stringWithFormat:@"Concrete method not implemented. Please implement %@ in %@", NSStringFromSelector(selector), NSStringFromClass(class)];
return [NSException exceptionWithName:@"Abstract Method Invocation Exception" reason:reason userInfo:nil];
}
@end
//
// NSString+Trim.h
// NSRegularExpression+BUYAdditions.h
// Mobile Buy SDK
//
// Created by Shopify.
......@@ -24,18 +24,18 @@
// THE SOFTWARE.
//
@import Foundation;
#import <Foundation/Foundation.h>
@interface NSRegularExpression (BUYAdditions)
/**
* Convenience method for easier white space and newline character trimming
* Return an array of strings which match the receiver in the given string.
*/
@interface NSString (Trim)
- (NSArray *)buy_matchesInString:(NSString *)string;
/**
* Equivalent to `[self stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]`
*
* @return NSString without white space and newline characters
*/
- (NSString*)buy_trim;
* Return the first match which matches the receiver in the given string.
*/
- (NSTextCheckingResult *)buy_firstMatchInString:(NSString *)string;
@end
//
// NSString+Trim.m
// NSRegularExpression+BUYAdditions.m
// Mobile Buy SDK
//
// Created by Shopify.
......@@ -24,13 +24,18 @@
// THE SOFTWARE.
//
#import "NSString+Trim.h"
#import "NSRegularExpression+BUYAdditions.h"
@implementation NSString (Trim)
@implementation NSRegularExpression (BUYAdditions)
- (NSString*)buy_trim
- (NSArray *)buy_matchesInString:(NSString *)string
{
return [self stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
return [self matchesInString:string options:0 range:NSMakeRange(0, string.length)];
}
- (NSTextCheckingResult *)buy_firstMatchInString:(NSString *)string
{
return [self firstMatchInString:string options:0 range:NSMakeRange(0, string.length)];
}
@end
//
// NSString+BUYAdditions.h
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
@import UIKit;
@interface NSString (BUYAdditions)
/**
* Return the current set of acronyms used when generating camel-case names;
*/
+ (NSArray *)buy_acronymStrings;
/**
* override built-in acronyms (which only contain "URL")
*/
+ (void)buy_setAcronymStrings:(NSArray *)strings;
/**
* Covert a snake-case string into a camel-case string
* Automatically UPPER-cases any tokens found in the current set of acronyms.
* @return a camel-case string
*/
- (NSString *)buy_camelCaseString;
/**
* Convert a camel-case string into a snake-case string
* @return a snake-case string
*/
- (NSString *)buy_snakeCaseString;
/**
* Return a string tokenized according to a camel-case pattern.
*/
- (NSArray *)buy_camelCaseTokens;
/**
* Return an array of string matches in the receiver for the given regular expression.
*/
- (NSArray *)buy_matchesForRegularExpression:(NSRegularExpression *)regex;
/**
* A convenience to return all matches in the receiver for the given regex pattern.
*/
- (NSArray *)buy_matchesForPattern:(NSString *)pattern;
/**
* As `-buy_matchesForRegularExpression`, but return only the first match.
*/
- (NSString *)buy_firstMatchForRegularExpression:(NSRegularExpression *)regex;
/**
* As `-buy_matchesForPattern`, but return only the first match.
*/
- (NSString *)buy_firstMatchForPattern:(NSString *)pattern;
/**
* Return a new string which reverses the UTF-8 characters of the receiver.
*/
- (NSString *)buy_reversedString;
/**
* @return the directory part of the file name, with no ending slash.
*/
@property (nonatomic, readonly) NSString *directory;
/**
* @return the file name without the extensions.
*/
@property (nonatomic, readonly) NSString *baseFileName;
/**
* @return a new string with updated directory path.
*/
- (NSString *)buy_stringByReplacingDirectory:(NSString *)newDirectory;
/**
* @return a new string replacing the base part of the name, preserving existing directory and extension.
*/
- (NSString *)buy_stringByReplacingBaseFileName:(NSString *)newName;
/**
* @return a new string with suffix appended to base file name, preserving existing directory and extension.
*/
- (NSString *)buy_stringByAppendingBaseFileNameSuffix:(NSString *)suffix;
/**
* @return a new string with HTML tags stripped from the receiver.
*/
- (NSString *)buy_stringByStrippingHTML;
/**
* @return a new attributed string with the specified attributes
*/
- (NSAttributedString *)buy_attributedStringWithLineSpacing:(CGFloat)spacing textAlignment:(NSTextAlignment)textAlignment;
/**
* Equivalent to `[self stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]`
*
* @return NSString without white space and newline characters
*/
- (NSString*)buy_trim;
@end
//
// NSString+BUYAdditions.m
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import "NSString+BUYAdditions.h"
#import "NSArray+BUYAdditions.h"
#import "NSRegularExpression+BUYAdditions.h"
/**
* A regex pattern that matches all lowercase roman characters and numbers at the beginning of a string.
*/
static NSString * const InitialTokenPattern = @"^[a-z][a-z0-9]*";
/**
* A regex pattern that matches a either one or more capitalized roman characters, or
* a sequence of lower-case and number characters followed by a capitalized roman character.
* This matches the reverse pattern of words in a camel-case string that are either UPPER case or Capitalized.
*/
static NSString * const ReverseSuccessiveTokenPattern = @"([A-Z]*|[a-z0-9]*)[A-Z]";
/**
* A convenience macro for converting a getter-style selector name into a string, to use in key-value coding.
*/
#define StringForSelector(sel) NSStringFromSelector(@selector(sel))
@implementation NSString (BUYAdditions)
#pragma mark - Transformations -
static NSSet *acronyms;
+ (NSSet *)buy_acronyms
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
acronyms = [NSSet setWithArray:@[ @"url" ]];
});
return acronyms;
}
+ (NSArray *)buy_acronymStrings
{
return [[self buy_acronyms] allObjects];
}
+ (void)buy_setAcronymStrings:(NSArray *)strings
{
acronyms = [NSSet setWithArray:[strings buy_map:^(NSString *string) {
return [string lowercaseString];
}]];
}
- (NSString *)buy_camelCaseString
{
NSArray *tokens = [self componentsSeparatedByString:@"_"];
NSArray *tailTokens = [tokens.buy_tail buy_map:^(NSString *token) {
return [token buy_camelCaseTailTokenForm];
}];
return [[tokens.firstObject buy_camelCaseFirstTokenForm] stringByAppendingString:[tailTokens componentsJoinedByString:@""]];
}
- (NSString *)buy_camelCaseFirstTokenForm
{
return [self isAcronym] ? [self uppercaseString] : self;
}
- (NSString *)buy_camelCaseTailTokenForm
{
return [self isAcronym] ? [self uppercaseString] : [self capitalizedString];
}
- (BOOL)isAcronym
{
return [[NSString buy_acronyms] containsObject:self];
}
- (NSString *)buy_snakeCaseString
{
return [[[self buy_camelCaseTokens] valueForKey:StringForSelector(lowercaseString)] componentsJoinedByString:@"_"];
}
- (NSArray *)buy_camelCaseTokens
{
NSString *first = [self buy_firstCamelCaseToken];
NSArray *rest = [self successiveCamelCaseTokens];
return first.length > 0 ? [@[first] arrayByAddingObjectsFromArray:rest] : rest;
}
- (NSString *)buy_firstCamelCaseToken
{
return [self buy_firstMatchForPattern:InitialTokenPattern];
}
- (NSArray *)successiveCamelCaseTokens
{
return [[[self.buy_reversedString buy_matchesForPattern:ReverseSuccessiveTokenPattern] valueForKey:StringForSelector(buy_reversedString)] buy_reversedArray];
}
- (NSArray *)buy_matchesForRegularExpression:(NSRegularExpression *)regex
{
return [[regex buy_matchesInString:self] buy_map:^id(NSTextCheckingResult *result) {
return [self substringWithRange:result.range];
}];
}
- (NSString *)buy_firstMatchForRegularExpression:(NSRegularExpression *)regex
{
return [self substringWithRange:[regex buy_firstMatchInString:self].range];
}
- (NSArray *)buy_matchesForPattern:(NSString *)pattern
{
return [self buy_matchesForRegularExpression:[NSRegularExpression regularExpressionWithPattern:pattern options:0 error:NULL]];
}
- (NSString *)buy_firstMatchForPattern:(NSString *)pattern
{
return [self buy_firstMatchForRegularExpression:[NSRegularExpression regularExpressionWithPattern:pattern options:0 error:NULL]];
}
- (NSString *)buy_reversedString
{
NSAssert([self canBeConvertedToEncoding:NSUTF8StringEncoding], @"Unable to reverse string; requires a string that can be encoded in UTF8");
const char *str = [self UTF8String];
unsigned long len = strlen(str);
char *rev = malloc(sizeof(char) * len + 1);
for (unsigned long i=0; i<len; ++i) {
rev[i] = str[len-i-1];
}
rev[len] = '\0';
NSString *reversedString = [NSString stringWithUTF8String:rev];
free(rev);
return reversedString;
}
#pragma mark - Path Extensions -
- (NSString *)directory
{
return [self stringByDeletingLastPathComponent];
}
- (NSString *)baseFileName
{
return [[self.pathComponents lastObject] stringByDeletingPathExtension];
}
- (NSString *)buy_stringByReplacingBaseFileName:(NSString *)newName
{
if (self.pathExtension.length > 0) {
newName = [newName stringByAppendingPathExtension:self.pathExtension];
}
return [self.directory stringByAppendingPathComponent:newName];
}
- (NSString *)buy_stringByReplacingDirectory:(NSString *)newDirectory
{
return [newDirectory stringByAppendingPathComponent:[self.baseFileName stringByAppendingPathExtension:self.pathExtension]];
}
- (NSString *)buy_stringByAppendingBaseFileNameSuffix:(NSString *)suffix
{
return [self buy_stringByReplacingBaseFileName:[self.baseFileName stringByAppendingString:suffix]];
}
- (NSString *)buy_stringByStrippingHTML
{
NSAttributedString *attributedString = [[NSAttributedString alloc] initWithData:[self dataUsingEncoding:NSUTF8StringEncoding]
options:@{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, NSCharacterEncodingDocumentAttribute: @(NSUTF8StringEncoding)}
documentAttributes:nil
error:nil];
return attributedString.string;
}
- (NSAttributedString *)buy_attributedStringWithLineSpacing:(CGFloat)spacing textAlignment:(NSTextAlignment)textAlignment
{
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:self];
NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init];
style.lineSpacing = spacing;
style.alignment = textAlignment;
[attributedString addAttribute:NSParagraphStyleAttributeName value:style range:NSMakeRange(0, self.length)];
return attributedString;
}
#pragma mark - Trim -
- (NSString*)buy_trim
{
return [self stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
}
@end
......@@ -35,6 +35,14 @@
*
* @return An NSURL from an NSString
*/
+ (NSURL *)buy_urlWithString:(NSString *)string;
+ (instancetype)buy_urlWithString:(NSString *)string;
/**
* Create an NSURL by updating the file name with the given suffix, preserving other URL properties.
*
* @return an NSURL object with the updated file name.
*/
- (instancetype)buy_URLByAppendingFileBaseNameSuffix:(NSString *)suffix;
@end
......@@ -25,10 +25,11 @@
//
#import "NSURL+BUYAdditions.h"
#import "NSString+BUYAdditions.h"
@implementation NSURL (BUYAdditions)
+ (NSURL *)buy_urlWithString:(NSString *)string
+ (instancetype)buy_urlWithString:(NSString *)string
{
NSURL *url = nil;
......@@ -39,5 +40,11 @@
return url;
}
- (instancetype)buy_URLByAppendingFileBaseNameSuffix:(NSString *)suffix
{
NSURLComponents *components = [NSURLComponents componentsWithURL:self resolvingAgainstBaseURL:NO];
components.path = [components.path buy_stringByAppendingBaseFileNameSuffix:suffix];
return [components URL];
}
@end
......@@ -25,8 +25,8 @@
//
#import "BUYAddress.h"
#import "NSString+Trim.h"
#import "NSDictionary+Additions.h"
#import "NSString+BUYAdditions.h"
#import "NSDictionary+BUYAdditions.h"
@implementation BUYAddress
......
......@@ -27,6 +27,7 @@
#import "BUYAddress.h"
#import "BUYCart.h"
#import "BUYCheckout.h"
#import "BUYCheckout_Private.h"
#import "BUYDiscount.h"
#import "BUYLineItem.h"
#import "BUYMaskedCreditCard.h"
......@@ -37,11 +38,10 @@
#import "BUYMaskedCreditCard.h"
#import "BUYGiftCard.h"
#import "NSDecimalNumber+BUYAdditions.h"
#import "NSString+Trim.h"
#import "BUYCheckout_Private.h"
#import "NSString+BUYAdditions.h"
#import "NSDateFormatter+BUYAdditions.h"
#import "NSURL+BUYAdditions.h"
#import "NSDictionary+Additions.h"
#import "NSDictionary+BUYAdditions.h"
#import "BUYCheckoutAttribute.h"
@implementation BUYCheckout
......
......@@ -27,7 +27,7 @@
#import "BUYCollection.h"
#import "NSDateFormatter+BUYAdditions.h"
#import "NSURL+BUYAdditions.h"
#import "NSDictionary+Additions.h"
#import "NSDictionary+BUYAdditions.h"
@interface BUYCollection ()
@property (nonatomic, strong) NSString *title;
......
......@@ -25,7 +25,7 @@
//
#import "BUYCreditCard.h"
#import "NSString+Trim.h"
#import "NSString+BUYAdditions.h"
@implementation BUYCreditCard
......
......@@ -26,7 +26,7 @@
#import "BUYDiscount.h"
#import "NSDecimalNumber+BUYAdditions.h"
#import "NSString+trim.h"
#import "NSString+BUYAdditions.h"
@implementation BUYDiscount
......
......@@ -27,7 +27,7 @@
#import "BUYLineItem.h"
#import "BUYProductVariant.h"
#import "NSDecimalNumber+BUYAdditions.h"
#import "NSString+Trim.h"
#import "NSString+BUYAdditions.h"
#import "BUYProduct.h"
@interface BUYLineItem ()
......
......@@ -26,7 +26,7 @@
#import "BUYOrder.h"
#import "NSURL+BUYAdditions.h"
#import "NSDictionary+Additions.h"
#import "NSDictionary+BUYAdditions.h"
@interface BUYOrder ()
......
......@@ -29,7 +29,7 @@
#import "BUYProduct.h"
#import "BUYProductVariant.h"
#import "NSDateFormatter+BUYAdditions.h"
#import "NSDictionary+Additions.h"
#import "NSDictionary+BUYAdditions.h"
@implementation BUYProduct
......
......@@ -26,7 +26,7 @@
#import "BUYShippingRate.h"
#import "NSDecimalNumber+BUYAdditions.h"
#import "NSString+Trim.h"
#import "NSString+BUYAdditions.h"
#import "NSDateFormatter+BUYAdditions.h"
@interface BUYShippingRate ()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment