Last active
March 10, 2025 23:43
-
-
Save prachigauriar/9739805 to your computer and use it in GitHub Desktop.
Code that reverses NSStrings using three different methods. Requires the `URLMock/TestHelpers` pod to generate random Unicode strings.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// main.m | |
// ReverseString | |
// | |
// Created by Prachi Gauriar on 3/23/2014. | |
// Copyright (c) 2014 Prachi Gauriar. All rights reserved. | |
// | |
#import <Foundation/Foundation.h> | |
#import <URLMock/UMKTestUtilities.h> | |
#define TIME(CALL, SUM_VARIABLE) \ | |
do { \ | |
NSTimeInterval startInterval = [NSDate timeIntervalSinceReferenceDate]; \ | |
CALL; \ | |
SUM_VARIABLE += [NSDate timeIntervalSinceReferenceDate] - startInterval; \ | |
} while (0) | |
@interface NSString (QLCReverse) | |
- (NSString *)qlc_reversedStringWithEnumerateSubstrings; | |
- (NSString *)qlc_reversedStringWithMemCopy; | |
- (NSString *)qlc_reversedStringWithUTF32Buffer; | |
@end | |
@implementation NSString (QLCReverse) | |
- (NSString *)qlc_reversedStringWithEnumerateSubstrings | |
{ | |
NSUInteger length = [self length]; | |
if (length < 2) { | |
return self; | |
} | |
NSMutableString *reversedString = [NSMutableString stringWithCapacity:length]; | |
[self enumerateSubstringsInRange:NSMakeRange(0, length) | |
options:(NSStringEnumerationReverse | NSStringEnumerationByComposedCharacterSequences) | |
usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) { | |
[reversedString appendString:substring]; | |
}]; | |
return reversedString; | |
} | |
- (NSString *)qlc_reversedStringWithMemCopy | |
{ | |
NSUInteger length = [self length]; | |
if (length < 2) { | |
return self; | |
} | |
unichar *characters = calloc(length, sizeof(unichar)); | |
unichar *reversedCharacters = calloc(length, sizeof(unichar)); | |
if (!characters || !reversedCharacters) { | |
free(characters); | |
free(reversedCharacters); | |
return nil; | |
} | |
[self getCharacters:characters range:NSMakeRange(0, length)]; | |
NSUInteger i = length - 1; | |
NSUInteger copiedCharacterCount = 0; | |
while (copiedCharacterCount < length) { | |
NSRange characterRange = [self rangeOfComposedCharacterSequenceAtIndex:i]; | |
memcpy(reversedCharacters + copiedCharacterCount, characters + characterRange.location, characterRange.length * sizeof(unichar)); | |
i = characterRange.location - 1; | |
copiedCharacterCount += characterRange.length; | |
} | |
free(characters); | |
NSString *reversedString = [[NSString alloc] initWithCharactersNoCopy:reversedCharacters length:length freeWhenDone:YES]; | |
if (!reversedString) { | |
free(reversedCharacters); | |
} | |
return reversedString; | |
} | |
- (NSString *)qlc_reversedStringWithUTF32Buffer | |
{ | |
NSUInteger length = [self length]; | |
if (length < 2) { | |
return self; | |
} | |
NSStringEncoding encoding = NSHostByteOrder() == NS_BigEndian ? NSUTF32BigEndianStringEncoding : NSUTF32LittleEndianStringEncoding; | |
NSUInteger utf32ByteCount = [self lengthOfBytesUsingEncoding:encoding]; | |
uint32_t *characters = malloc(utf32ByteCount); | |
if (!characters) { | |
return nil; | |
} | |
[self getBytes:characters maxLength:utf32ByteCount usedLength:NULL encoding:encoding options:0 range:NSMakeRange(0, length) remainingRange:NULL]; | |
NSUInteger utf32Length = utf32ByteCount / sizeof(uint32_t); | |
NSUInteger halfwayPoint = utf32Length / 2; | |
for (NSUInteger i = 0; i < halfwayPoint; ++i) { | |
uint32_t character = characters[utf32Length - i - 1]; | |
characters[utf32Length - i - 1] = characters[i]; | |
characters[i] = character; | |
} | |
return [[NSString alloc] initWithBytesNoCopy:characters length:utf32ByteCount encoding:encoding freeWhenDone:YES]; | |
} | |
@end | |
int main(int argc, const char * argv[]) | |
{ | |
srandomdev(); | |
for (NSUInteger j = 0; j < 5; ++j) { | |
NSTimeInterval enumerateSubstringsTime = 0.0; | |
NSTimeInterval memcpyTime = 0.0; | |
NSTimeInterval utf32Time = 0.0; | |
for (NSUInteger i = 0; i < 100000; ++i) { | |
@autoreleasepool { | |
NSString *string = UMKRandomUnicodeString(); | |
TIME([string qlc_reversedStringWithEnumerateSubstrings], enumerateSubstringsTime); | |
TIME([string qlc_reversedStringWithMemCopy], memcpyTime); | |
TIME([string qlc_reversedStringWithUTF32Buffer], utf32Time); | |
} | |
} | |
NSLog(@"Enumerate substrings: %.6f", enumerateSubstringsTime); | |
NSLog(@"MemCopy: %.6f", memcpyTime); | |
NSLog(@"UTF-32: %.6f", utf32Time); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment