Skip to content

Instantly share code, notes, and snippets.

@prachigauriar
Last active November 24, 2020 08:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save prachigauriar/9739805 to your computer and use it in GitHub Desktop.
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.
//
// 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