//  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  Steve Nygard

#import "NSScanner-Extensions.h"

#import "NSString-Extensions.h"

@implementation NSScanner (CDExtensions)

// gs for GnuSpeech
+ (NSCharacterSet *)gsBooleanIdentifierCharacterSet;
{
    static NSCharacterSet *identifierCharacterSet = nil;

    if (identifierCharacterSet == nil) {
        NSMutableCharacterSet *aSet = [[NSCharacterSet letterCharacterSet] mutableCopy];
        [aSet addCharactersInString:@"'"];
        identifierCharacterSet = [aSet copy];
    }

    return identifierCharacterSet;
}

- (NSString *)peekCharacter;
{
    //[self skipCharacters];

    if ([self isAtEnd])
        return nil;

    return [[self string] substringWithRange:NSMakeRange([self scanLocation], 1)];
}

- (unichar)peekChar;
{
    return [[self string] characterAtIndex:[self scanLocation]];
}

- (BOOL)scanCharacter:(unichar *)value;
{
    //[self skipCharacters];

    if ([self isAtEnd])
        return NO;

    unichar ch = [[self string] characterAtIndex:[self scanLocation]];
    if (value != NULL)
        *value = ch;

    [self setScanLocation:[self scanLocation] + 1];

    return YES;
}

- (BOOL)scanCharacterIntoString:(NSString **)value;
{
    unichar ch;

    BOOL result = [self scanCharacter:&ch];
    if (result)
        *value = [NSString stringWithUnichar:ch];

    return result;
}

- (BOOL)scanCharacterFromString:(NSString *)aString intoString:(NSString **)value;
{
    return [self scanCharacterFromSet:[NSCharacterSet characterSetWithCharactersInString:aString] intoString:value];
}

- (BOOL)scanCharacterFromSet:(NSCharacterSet *)set intoString:(NSString **)value;
{
    //[self skipCharacters];

    if ([self isAtEnd])
        return NO;

    unichar ch = [[self string] characterAtIndex:[self scanLocation]];
    if ([set characterIsMember:ch]) {
        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;

    //[self skipCharacters];

    NSUInteger currentLocation = [self scanLocation];
    matchedRange.location = currentLocation;
    matchedRange.length = 0;

    while ([self isAtEnd] == NO) {
        unichar 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]) {
        return YES;
    }

    if ([self scanCharacterFromSet:[NSCharacterSet letterCharacterSet] intoString:&start]) {
        NSString *str;

        if ([self my_scanCharactersFromSet:[NSCharacterSet alphanumericCharacterSet] intoString:&remainder]) {
            str = [start stringByAppendingString:remainder];
        } else {
            str = start;
        }

        if (stringPointer != NULL)
            *stringPointer = str;

        return YES;
    }

    return NO;
}

@end
