Skip to content

Instantly share code, notes, and snippets.

@krackers
Forked from 0xced/NSString.m
Created April 5, 2024 18:51
Show Gist options
  • Save krackers/41156714eb3e19c128bfd81c8c67965c to your computer and use it in GitHub Desktop.
Save krackers/41156714eb3e19c128bfd81c8c67965c to your computer and use it in GitHub Desktop.
Reverse-engineered implementation of -[NSString isEqual:] and -[NSString isEqualToString:]
/*
* Most NSString instances will actually be __NSCFString instances, so here are both NSString and __NSCFString implementations.
* If you know how to create an NSString instance whose class is actually NSString please let me know.
* Other possible concrete subclasses of NSString are: NSConstantString, __NSCFConstantString, NSPathStore2, NSSimpleCString and __NSLocalizedString.
*/
// CoreFoundation.framework 635.19.0 (Mac OS X 10.7.3)
@implementation NSObject
- (BOOL) isNSString__
{
return NO;
}
@end
@implementation __NSCFString
static CFStringEncoding enc = 0;
- (BOOL) isNSString__
{
return YES;
}
- (BOOL) isEqual:(id)string
{
if (self == string)
{
return YES;
}
else if (string == nil)
{
return NO
}
else
{
Class stringClass = [string class];
Class nscfStringClass = objc_lookUpClass("__NSCFString");
if (stringClass == nscfStringClass || class_getSuperclass(stringClass) == nscfStringClass)
{
if (enc == kCFStringEncodingInvalidId)
enc = CFStringGetSystemEncoding();
const char *selfCString = CFStringGetCStringPtr(self, enc);
if (enc == kCFStringEncodingInvalidId)
enc = CFStringGetSystemEncoding();
const char *argCString = CFStringGetCStringPtr(string, enc);
if (selfCString != NULL && argCString != NULL)
{
CFIndex length = _CFStringGetLength2(self);
if (length == _CFStringGetLength2(string))
{
return memcmp(selfCString, argCString, length) == 0;
}
else
{
return NO;
}
}
}
}
if (![string isNSString__])
return NO;
// Eventually calls __CFStringEqual whose implementation is available at http://opensource.apple.com/source/CF/CF-635.19/CFString.c
return CFEqual(self, string);
}
- (BOOL) isEqualToString:(NSString *)string
{
if (self == string)
{
return YES;
}
else if (string == nil)
{
return NO
}
else
{
Class stringClass = [string class];
Class nscfStringClass = objc_lookUpClass("__NSCFString");
if (stringClass == nscfStringClass || class_getSuperclass(stringClass) == nscfStringClass)
{
if (enc == kCFStringEncodingInvalidId)
enc = CFStringGetSystemEncoding();
const char *selfCString = CFStringGetCStringPtr(self, enc);
if (enc == kCFStringEncodingInvalidId)
enc = CFStringGetSystemEncoding();
const char *argCString = CFStringGetCStringPtr(string, enc);
if (selfCString != NULL && argCString != NULL)
{
CFIndex length = _CFStringGetLength2(self);
if (length == _CFStringGetLength2(string))
{
return memcmp(selfCString, argCString, length) == 0;
}
else
{
return NO;
}
}
}
}
// Eventually calls __CFStringEqual whose implementation is available at http://opensource.apple.com/source/CF/CF-635.19/CFString.c
return CFEqual(self, string);
}
@end
// Foundation.framework 833.24.0 (Mac OS X 10.7.3)
@implementation NSString
- (BOOL) isNSString__
{
return YES;
}
- (BOOL) isEqual:(id)string
{
if ([string isNSString__])
return [self isEqualToString:string];
else
return NO;
}
- (BOOL) isEqualToString:(NSString *)string
{
if (self == string)
return YES;
else
return [self compare:string options:NSLiteralSearch range:NSMakeRange(0, [self length])] == NSOrderedSame;
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment