blob: 8fe475cb95ed92577b851ec88de4ebae2eb5a532 [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-2019 Steve Nygard.
#import "CDProtocolUniquer.h"
#import "CDOCProtocol.h"
#import "CDOCMethod.h"
@implementation CDProtocolUniquer
{
NSMutableDictionary *_protocolsByAddress; // non-uniqued
NSMutableDictionary *_uniqueProtocolsByName;
NSMutableDictionary *_uniqueProtocolsByAddress;
}
- (id)init;
{
if ((self = [super init])) {
_protocolsByAddress = [[NSMutableDictionary alloc] init];
_uniqueProtocolsByName = [[NSMutableDictionary alloc] init];
_uniqueProtocolsByAddress = [[NSMutableDictionary alloc] init];
}
return self;
}
#pragma mark - Gather
- (CDOCProtocol *)protocolWithAddress:(uint64_t)address;
{
NSNumber *key = [NSNumber numberWithUnsignedLongLong:address];
return _protocolsByAddress[key];
}
- (void)setProtocol:(CDOCProtocol *)protocol withAddress:(uint64_t)address;
{
NSNumber *key = [NSNumber numberWithUnsignedLongLong:address];
_protocolsByAddress[key] = protocol;
}
#pragma mark - Process
- (void)createUniquedProtocols;
{
[_uniqueProtocolsByName removeAllObjects];
[_uniqueProtocolsByAddress removeAllObjects];
// Now unique the protocols by name and store in protocolsByName
for (NSNumber *key in [[_protocolsByAddress allKeys] sortedArrayUsingSelector:@selector(compare:)]) {
CDOCProtocol *p1 = _protocolsByAddress[key];
CDOCProtocol *uniqueProtocol = _uniqueProtocolsByName[p1.name];
if (uniqueProtocol == nil) {
uniqueProtocol = [[CDOCProtocol alloc] init];
[uniqueProtocol setName:[p1 name]];
_uniqueProtocolsByName[uniqueProtocol.name] = uniqueProtocol;
// adopted protocols still not set, will want uniqued instances
} else {
}
_uniqueProtocolsByAddress[key] = uniqueProtocol;
}
//NSLog(@"uniqued protocol names: %@", [[[protocolsByName allKeys] sortedArrayUsingSelector:@selector(compare:)] componentsJoinedByString:@", "]);
// And finally fill in adopted protocols, instance and class methods. And properties.
for (NSNumber *key in [[_protocolsByAddress allKeys] sortedArrayUsingSelector:@selector(compare:)]) {
CDOCProtocol *p1 = _protocolsByAddress[key];
CDOCProtocol *uniqueProtocol = _uniqueProtocolsByName[p1.name];
// Add the uniqued adopted protocols
for (CDOCProtocol *p2 in [p1 protocols])
[uniqueProtocol addProtocol:_uniqueProtocolsByName[p2.name]];
[uniqueProtocol mergeMethodsFromProtocol:p1];
[uniqueProtocol mergePropertiesFromProtocol:p1];
}
//NSLog(@"protocolsByName: %@", protocolsByName);
}
#pragma mark - Results
// These are useful after the call to -createUniqueProtocols
- (NSArray *)uniqueProtocolsAtAddresses:(NSArray *)addresses;
{
NSMutableArray *protocols = [NSMutableArray array];
for (NSNumber *protocolAddress in addresses) {
CDOCProtocol *uniqueProtocol = _uniqueProtocolsByAddress[protocolAddress];
if (uniqueProtocol != nil)
[protocols addObject:uniqueProtocol];
}
return [protocols copy];
}
- (NSArray *)uniqueProtocolsSortedByName;
{
return [[_uniqueProtocolsByName allValues] sortedArrayUsingSelector:@selector(ascendingCompareByName:)];
}
@end