Skip to content

Instantly share code, notes, and snippets.

@bgulanowski
Created August 23, 2015 03:25
Show Gist options
  • Save bgulanowski/2105c214aa305800e9be to your computer and use it in GitHub Desktop.
Save bgulanowski/2105c214aa305800e9be to your computer and use it in GitHub Desktop.
//
// NSString+SnakeMaking.h
// Test
//
// Created by Brent Gulanowski on 2015-08-22.
// Copyright (c) 2015 Lichen Labs. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface NSString (SnakeMaking)
- (NSString *)snakeCaseString;
- (NSString *)snakeCaseStringNumbersAsWords;
@end
@interface NSString (RegularExpressionMatching)
- (NSArray *)matchesForRegularExpression:(NSRegularExpression *)regex;
- (NSArray *)matchesForPattern:(NSString *)pattern;
- (NSString *)firstMatchForRegularExpression:(NSRegularExpression *)regex;
- (NSString *)firstMatchForPattern:(NSString *)pattern;
@end
@interface NSString (CamelCaseMatching)
- (NSArray *)camelCaseTokens;
- (NSArray *)camelCaseTokensNumbersAsWords;
@end
@interface NSString (Reversing)
- (NSString *)reversedString;
@end
@interface NSRegularExpression (SimplifiedMatching)
- (NSArray *)matchesInString:(NSString *)string;
- (NSTextCheckingResult *)firstMatchInString:(NSString *)string;
@end
@interface NSTextCheckingResult (StringMatching)
- (NSString *)stringForMatchInString:(NSString *)string;
@end
@interface NSArray (Mapping)
- (NSArray *)map:(id(^)(id object))block;
- (NSArray *)reversedArray;
@end
@interface NSMutableArray (Reversing)
- (void)reverse;
@end
//
// NSString+SnakeMaking.m
// Test
//
// Created by Brent Gulanowski on 2015-08-22.
// Copyright (c) 2015 Lichen Labs. All rights reserved.
//
#import "NSString+SnakeMaking.h"
static NSString * const InitialTokenPattern = @"^[a-z][a-z0-9]*";
static NSString * const InitialWordOrNumberTokenPattern = @"^[a-z]+|[0-9]+";
static NSString * const ReverseSuccessiveTokenPattern = @"([A-Z]*|[a-z0-9]*)[A-Z]";
static NSString * const ReverseSuccessiveWordOrNumberTokenPattern = @"([A-Z]*|[a-z]*)[A-Z]|[0-9]+";
#define StringForSelector(sel) NSStringFromSelector(@selector(sel))
@implementation NSString (SnakeMaking)
- (NSString *)snakeCaseString
{
return [[[self camelCaseTokens] valueForKey:StringForSelector(lowercaseString)] componentsJoinedByString:@"_"];
}
- (NSString *)snakeCaseStringNumbersAsWords
{
return [[[self camelCaseTokensNumbersAsWords] valueForKey:StringForSelector(lowercaseString)] componentsJoinedByString:@"_"];
}
@end
#pragma mark -
@implementation NSString (RegularExpressionMatching)
- (NSArray *)matchesForRegularExpression:(NSRegularExpression *)regex
{
return [[regex matchesInString:self] map:^id(NSTextCheckingResult *result) {
return [result stringForMatchInString:self];
}];
}
- (NSArray *)matchesForPattern:(NSString *)pattern
{
return [self matchesForRegularExpression:[NSRegularExpression regularExpressionWithPattern:pattern options:0 error:NULL]];
}
- (NSString *)firstMatchForRegularExpression:(NSRegularExpression *)regex
{
return [[regex firstMatchInString:self] stringForMatchInString:self];
}
- (NSString *)firstMatchForPattern:(NSString *)pattern
{
return [self firstMatchForRegularExpression:[NSRegularExpression regularExpressionWithPattern:pattern options:0 error:NULL]];
}
@end
#pragma mark -
@implementation NSString (CamelCaseMatching)
+ (NSString *)initialTokenPatternNumbersAsWords:(BOOL)numbersAsWords
{
return (numbersAsWords ? InitialWordOrNumberTokenPattern : InitialTokenPattern);
}
+ (NSString *)successiveTokenPatternNumbersAsWords:(BOOL)numbersAsWords
{
return (numbersAsWords ? ReverseSuccessiveWordOrNumberTokenPattern : ReverseSuccessiveTokenPattern);
}
- (NSString *)firstCamelCaseTokenNumbersAsWords:(BOOL)numbersAsWords
{
return [self firstMatchForPattern:[NSString initialTokenPatternNumbersAsWords:numbersAsWords]];
}
- (NSArray *)successiveCamelCaseTokensNumbersAsWords:(BOOL)numbersAsWords
{
return [[[self.reversedString matchesForPattern:[NSString successiveTokenPatternNumbersAsWords:numbersAsWords]] valueForKey:StringForSelector(reversedString)] reversedArray];
}
- (NSArray *)camelCaseTokensTreatNumbersAsWords:(BOOL)numbersAsWords
{
NSString *first = [self firstCamelCaseTokenNumbersAsWords:numbersAsWords];
NSArray *rest = [self successiveCamelCaseTokensNumbersAsWords:numbersAsWords];
return first.length > 0 ? [@[first] arrayByAddingObjectsFromArray:rest] : rest;
}
- (NSArray *)camelCaseTokens
{
return [self camelCaseTokensTreatNumbersAsWords:NO];
}
- (NSArray *)camelCaseTokensNumbersAsWords
{
return [self camelCaseTokensTreatNumbersAsWords:YES];
}
@end
#pragma mark -
@implementation NSString (Reversing)
- (NSString *)reversedString
{
// This probably does terrible things to multi-byte characters :(
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;
}
@end
#pragma mark -
@implementation NSRegularExpression (SimplifiedMatching)
- (NSArray *)matchesInString:(NSString *)string
{
return [self matchesInString:string options:0 range:NSMakeRange(0, string.length)];
}
- (NSTextCheckingResult *)firstMatchInString:(NSString *)string
{
return [self firstMatchInString:string options:0 range:NSMakeRange(0, string.length)];
}
@end
#pragma mark -
@implementation NSTextCheckingResult (StringMatching)
- (NSString *)stringForMatchInString:(NSString *)string
{
return [string substringWithRange:self.range];
}
@end
#pragma mark -
@implementation NSArray (Mapping)
- (NSArray *)reversedArray
{
NSMutableArray *array = [self mutableCopy];
[array reverse];
return array;
}
- (NSArray *)map:(id(^)(id object))block
{
NSMutableArray *array = [NSMutableArray array];
[self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
[array addObject:block(obj)];
}];
return array;
}
@end
#pragma mark -
@implementation NSMutableArray (Mapping)
- (void)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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment