blob: d5a392a6aa164e54f00019494de92cdf4bb9eaef [file] [log] [blame]
// -*- mode: ObjC -*-
// 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-2009 Steve Nygard.
#import "CDBalanceFormatter.h"
#import "NSString-Extensions.h"
static BOOL debug = NO;
@implementation CDBalanceFormatter
- (id)initWithString:(NSString *)str;
{
if ([super init] == nil)
return nil;
scanner = [[NSScanner alloc] initWithString:str];
openCloseSet = [[NSCharacterSet characterSetWithCharactersInString:@"{}<>()"] retain];
result = [[NSMutableString alloc] init];
return self;
}
- (void)dealloc;
{
[scanner release];
[openCloseSet release];
[result release];
[super dealloc];
}
- (void)parse:(NSString *)open index:(NSUInteger)openIndex level:(NSUInteger)level;
{
NSArray *pairs;
NSString *pre;
NSString *opens[] = { @"{", @"<", @"(", nil};
NSString *closes[] = { @"}", @">", @")", nil};
NSUInteger index;
BOOL foundOpen = NO;
BOOL foundClose = NO;
pairs = [[NSArray alloc] initWithObjects:@"{}", @"<>", @"()", nil];
while ([scanner isAtEnd] == NO) {
if ([scanner scanUpToCharactersFromSet:openCloseSet intoString:&pre]) {
if (debug) NSLog(@"pre = '%@'", pre);
[result appendFormat:@"%@%@\n", [NSString spacesIndentedToLevel:level], pre];
}
if (debug) NSLog(@"remaining: '%@'", [[scanner string] substringFromIndex:[scanner scanLocation]]);
foundOpen = foundClose = NO;
for (index = 0; index < 3; index++) {
if (debug) NSLog(@"Checking open %u: '%@'", index, opens[index]);
if ([scanner scanString:opens[index] intoString:NULL]) {
if (debug) NSLog(@"Start %@", opens[index]);
[result appendSpacesIndentedToLevel:level];
[result appendString:opens[index]];
[result appendString:@"\n"];
[self parse:opens[index] index:[scanner scanLocation] - 1 level:level + 1];
[result appendSpacesIndentedToLevel:level];
[result appendString:closes[index]];
[result appendString:@"\n"];
foundOpen = YES;
break;
}
if (debug) NSLog(@"Checking close %u: '%@'", index, closes[index]);
if ([scanner scanString:closes[index] intoString:NULL]) {
if ([open isEqualToString:opens[index]]) {
if (debug) NSLog(@"End %@", closes[index]);
} else {
NSLog(@"ERROR: Unmatched end %@", closes[index]);
}
foundClose = YES;
break;
}
}
if (foundOpen == NO && foundClose == NO) {
if (debug) NSLog(@"Unknown @ %u: %@", [scanner scanLocation], [[scanner string] substringFromIndex:[scanner scanLocation]]);
break;
}
if (foundClose)
break;
}
[pairs release];
}
- (NSString *)format;
{
[self parse:nil index:0 level:0];
if (debug) NSLog(@"result:\n%@", result);
return [NSString stringWithString:result];
}
@end