Move the class map to a CFDictionary.

Since the keys are `Class`-s, there's no need to hash/copy/etc. them. This
avoids causing `+initialize` on the classes just when building up a registry.
pull/8329/head
Thomas Van Lenten 4 years ago
parent 133e5e7526
commit 5911099659
  1. 49
      objectivec/GPBExtensionRegistry.m

@ -34,18 +34,20 @@
#import "GPBDescriptor.h" #import "GPBDescriptor.h"
@implementation GPBExtensionRegistry { @implementation GPBExtensionRegistry {
NSMutableDictionary *mutableClassMap_; CFMutableDictionaryRef mutableClassMap_;
} }
- (instancetype)init { - (instancetype)init {
if ((self = [super init])) { if ((self = [super init])) {
mutableClassMap_ = [[NSMutableDictionary alloc] init]; // The keys are ObjC classes, so straight up ptr comparisons are fine.
mutableClassMap_ = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, NULL,
&kCFTypeDictionaryValueCallBacks);
} }
return self; return self;
} }
- (void)dealloc { - (void)dealloc {
[mutableClassMap_ release]; CFRelease(mutableClassMap_);
[super dealloc]; [super dealloc];
} }
@ -68,14 +70,13 @@
Class containingMessageClass = extension.containingMessageClass; Class containingMessageClass = extension.containingMessageClass;
CFMutableDictionaryRef extensionMap = (CFMutableDictionaryRef) CFMutableDictionaryRef extensionMap = (CFMutableDictionaryRef)
[mutableClassMap_ objectForKey:containingMessageClass]; CFDictionaryGetValue(mutableClassMap_, containingMessageClass);
if (extensionMap == nil) { if (extensionMap == nil) {
// Use a custom dictionary here because the keys are numbers and conversion // Use a custom dictionary here because the keys are numbers and conversion
// back and forth from NSNumber isn't worth the cost. // back and forth from NSNumber isn't worth the cost.
extensionMap = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, NULL, extensionMap = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, NULL,
&kCFTypeDictionaryValueCallBacks); &kCFTypeDictionaryValueCallBacks);
[mutableClassMap_ setObject:(id)extensionMap CFDictionarySetValue(mutableClassMap_, containingMessageClass, extensionMap);
forKey:(id<NSCopying>)containingMessageClass];
CFRelease(extensionMap); CFRelease(extensionMap);
} }
@ -87,7 +88,7 @@
fieldNumber:(NSInteger)fieldNumber { fieldNumber:(NSInteger)fieldNumber {
Class messageClass = descriptor.messageClass; Class messageClass = descriptor.messageClass;
CFMutableDictionaryRef extensionMap = (CFMutableDictionaryRef) CFMutableDictionaryRef extensionMap = (CFMutableDictionaryRef)
[mutableClassMap_ objectForKey:messageClass]; CFDictionaryGetValue(mutableClassMap_, messageClass);
ssize_t key = fieldNumber; ssize_t key = fieldNumber;
GPBExtensionDescriptor *result = GPBExtensionDescriptor *result =
(extensionMap (extensionMap
@ -101,28 +102,28 @@ static void CopyKeyValue(const void *key, const void *value, void *context) {
CFDictionarySetValue(extensionMap, key, value); CFDictionarySetValue(extensionMap, key, value);
} }
static void CopySubDictionary(const void *key, const void *value, void *context) {
CFMutableDictionaryRef mutableClassMap = (CFMutableDictionaryRef)context;
Class containingMessageClass = key;
CFMutableDictionaryRef otherExtensionMap = (CFMutableDictionaryRef)value;
CFMutableDictionaryRef extensionMap = (CFMutableDictionaryRef)
CFDictionaryGetValue(mutableClassMap, containingMessageClass);
if (extensionMap == nil) {
extensionMap = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, otherExtensionMap);
CFDictionarySetValue(mutableClassMap, containingMessageClass, extensionMap);
CFRelease(extensionMap);
} else {
CFDictionaryApplyFunction(otherExtensionMap, CopyKeyValue, extensionMap);
}
}
- (void)addExtensions:(GPBExtensionRegistry *)registry { - (void)addExtensions:(GPBExtensionRegistry *)registry {
if (registry == nil) { if (registry == nil) {
// In the case where there are no extensions just ignore. // In the case where there are no extensions just ignore.
return; return;
} }
NSMutableDictionary *otherClassMap = registry->mutableClassMap_; CFDictionaryApplyFunction(registry->mutableClassMap_, CopySubDictionary, mutableClassMap_);
[otherClassMap enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL * stop) {
#pragma unused(stop)
Class containingMessageClass = key;
CFMutableDictionaryRef otherExtensionMap = (CFMutableDictionaryRef)value;
CFMutableDictionaryRef extensionMap = (CFMutableDictionaryRef)
[mutableClassMap_ objectForKey:containingMessageClass];
if (extensionMap == nil) {
extensionMap = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, otherExtensionMap);
[mutableClassMap_ setObject:(id)extensionMap
forKey:(id<NSCopying>)containingMessageClass];
CFRelease(extensionMap);
} else {
CFDictionaryApplyFunction(otherExtensionMap, CopyKeyValue, extensionMap);
}
}];
} }
#pragma clang diagnostic pop #pragma clang diagnostic pop

Loading…
Cancel
Save