blob: 13477e5a31a095aacc7599e0eda0874dd10159ce [file] [log] [blame]
// This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files.
// Copyright (C) 1997-1998, 2000-2001, 2004-2007 Steve Nygard
#import "NSScanner-Extensions.h"
#import <Foundation/Foundation.h>
#import "NSString-Extensions.h"
@implementation NSScanner (CDExtensions)
// other: $_:*
// start: alpha + other
// remainder: alnum + other
+ (NSCharacterSet *)cdOtherCharacterSet;
{
static NSCharacterSet *otherCharacterSet = nil;
if (otherCharacterSet == nil)
otherCharacterSet = [[NSCharacterSet characterSetWithCharactersInString:@"$_:*"] retain];
return otherCharacterSet;
}
+ (NSCharacterSet *)cdIdentifierStartCharacterSet;
{
static NSCharacterSet *identifierStartCharacterSet = nil;
if (identifierStartCharacterSet == nil) {
NSMutableCharacterSet *aSet;
aSet = [[NSCharacterSet letterCharacterSet] mutableCopy];
[aSet formUnionWithCharacterSet:[NSScanner cdOtherCharacterSet]];
identifierStartCharacterSet = [aSet copy];
[aSet release];
}
return identifierStartCharacterSet;
}
+ (NSCharacterSet *)cdIdentifierCharacterSet;
{
static NSCharacterSet *identifierCharacterSet = nil;
if (identifierCharacterSet == nil) {
NSMutableCharacterSet *aSet;
aSet = [[NSCharacterSet alphanumericCharacterSet] mutableCopy];
[aSet formUnionWithCharacterSet:[NSScanner cdOtherCharacterSet]];
identifierCharacterSet = [aSet copy];
[aSet release];
}
return identifierCharacterSet;
}
+ (NSCharacterSet *)cdTemplateTypeCharacterSet;
{
static NSCharacterSet *templateTypeCharacterSet = nil;
if (templateTypeCharacterSet == nil)
templateTypeCharacterSet = [[[NSCharacterSet characterSetWithCharactersInString:@"<,>"] invertedSet] retain];
return templateTypeCharacterSet;
}
- (NSString *)peekCharacter;
{
//[self skipCharacters];
if ([self isAtEnd] == YES)
return nil;
return [[self string] substringWithRange:NSMakeRange([self scanLocation], 1)];
}
- (unichar)peekChar;
{
return [[self string] characterAtIndex:[self scanLocation]];
}
- (BOOL)scanCharacter:(unichar *)value;
{
unichar ch;
//[self skipCharacters];
if ([self isAtEnd] == YES)
return NO;
ch = [[self string] characterAtIndex:[self scanLocation]];
if (value != NULL)
*value = ch;
[self setScanLocation:[self scanLocation] + 1];
return YES;
}
- (BOOL)scanCharacterFromSet:(NSCharacterSet *)set intoString:(NSString **)value;
{
unichar ch;
//[self skipCharacters];
if ([self isAtEnd] == YES)
return NO;
ch = [[self string] characterAtIndex:[self scanLocation]];
if ([set characterIsMember:ch] == YES) {
if (value != NULL) {
*value = [NSString stringWithUnichar:ch];
}
[self setScanLocation:[self scanLocation] + 1];
return YES;
}
return NO;
}
// On 10.3 (7D24) the Foundation scanCharactersFromSet:intoString: inverts the set each call, creating an autoreleased CFCharacterSet.
// This cuts the total CFCharacterSet alloctions (when run on Foundation) from 161682 down to 17.
// This works for my purposes, but I haven't tested it to make sure it's fully compatible with the standard version.
- (BOOL)my_scanCharactersFromSet:(NSCharacterSet *)set intoString:(NSString **)value;
{
NSRange matchedRange;
unsigned int currentLocation;
NSCharacterSet *skipSet;
currentLocation = [self scanLocation];
// Skip over characters
skipSet = [self charactersToBeSkipped];
while ([self isAtEnd] == NO) {
unichar ch;
ch = [[self string] characterAtIndex:currentLocation];
if ([skipSet characterIsMember:ch] == NO)
break;
currentLocation++;
[self setScanLocation:currentLocation];
}
matchedRange.location = currentLocation;
matchedRange.length = 0;
while ([self isAtEnd] == NO) {
unichar ch;
ch = [[self string] characterAtIndex:currentLocation];
if ([set characterIsMember:ch] == NO)
break;
currentLocation++;
[self setScanLocation:currentLocation];
}
matchedRange.length = currentLocation - matchedRange.location;
if (matchedRange.length == 0)
return NO;
if (value != NULL) {
*value = [[self string] substringWithRange:matchedRange];
}
return YES;
}
- (BOOL)scanIdentifierIntoString:(NSString **)stringPointer;
{
NSString *start, *remainder;
if ([self scanString:@"?" intoString:stringPointer] == YES) {
return YES;
}
if ([self scanCharacterFromSet:[NSScanner cdIdentifierStartCharacterSet] intoString:&start] == YES) {
NSString *str;
if ([self my_scanCharactersFromSet:[NSScanner cdIdentifierCharacterSet] intoString:&remainder] == YES) {
str = [start stringByAppendingString:remainder];
} else {
str = start;
}
if (stringPointer != NULL)
*stringPointer = str;
return YES;
}
return NO;
}
@end