Index: third_party/protobuf/objectivec/GPBExtensionRegistry.m |
diff --git a/third_party/protobuf/objectivec/GPBExtensionRegistry.m b/third_party/protobuf/objectivec/GPBExtensionRegistry.m |
index df61a17b187ab1d21894e0da8e4b33939491e935..65534b67af1692689cea292e65dc5f8ce577764a 100644 |
--- a/third_party/protobuf/objectivec/GPBExtensionRegistry.m |
+++ b/third_party/protobuf/objectivec/GPBExtensionRegistry.m |
@@ -34,8 +34,6 @@ |
#import "GPBDescriptor.h" |
@implementation GPBExtensionRegistry { |
- // TODO(dmaclach): Reimplement with CFDictionaries that don't use |
- // objects as keys. |
NSMutableDictionary *mutableClassMap_; |
} |
@@ -51,6 +49,12 @@ |
[super dealloc]; |
} |
+// Direct access is use for speed, to avoid even internally declaring things |
+// read/write, etc. The warning is enabled in the project to ensure code calling |
+// protos can turn on -Wdirect-ivar-access without issues. |
+#pragma clang diagnostic push |
+#pragma clang diagnostic ignored "-Wdirect-ivar-access" |
+ |
- (instancetype)copyWithZone:(NSZone *)zone { |
GPBExtensionRegistry *result = [[[self class] allocWithZone:zone] init]; |
if (result && mutableClassMap_.count) { |
@@ -59,13 +63,16 @@ |
return result; |
} |
-- (NSMutableDictionary *)extensionMapForContainingMessageClass: |
+- (CFMutableDictionaryRef)extensionMapForContainingMessageClass: |
(Class)containingMessageClass { |
- NSMutableDictionary *extensionMap = |
+ CFMutableDictionaryRef extensionMap = (CFMutableDictionaryRef) |
[mutableClassMap_ objectForKey:containingMessageClass]; |
if (extensionMap == nil) { |
- extensionMap = [NSMutableDictionary dictionary]; |
- [mutableClassMap_ setObject:extensionMap |
+ // Use a custom dictionary here because the keys are numbers and conversion |
+ // back and forth from NSNumber isn't worth the cost. |
+ extensionMap = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, NULL, |
+ &kCFTypeDictionaryValueCallBacks); |
+ [mutableClassMap_ setObject:(id)extensionMap |
forKey:(id<NSCopying>)containingMessageClass]; |
} |
return extensionMap; |
@@ -77,17 +84,28 @@ |
} |
Class containingMessageClass = extension.containingMessageClass; |
- NSMutableDictionary *extensionMap = |
+ CFMutableDictionaryRef extensionMap = |
[self extensionMapForContainingMessageClass:containingMessageClass]; |
- [extensionMap setObject:extension forKey:@(extension.fieldNumber)]; |
+ ssize_t key = extension.fieldNumber; |
+ CFDictionarySetValue(extensionMap, (const void *)key, extension); |
} |
- (GPBExtensionDescriptor *)extensionForDescriptor:(GPBDescriptor *)descriptor |
fieldNumber:(NSInteger)fieldNumber { |
Class messageClass = descriptor.messageClass; |
- NSDictionary *extensionMap = |
+ CFMutableDictionaryRef extensionMap = (CFMutableDictionaryRef) |
[mutableClassMap_ objectForKey:messageClass]; |
- return [extensionMap objectForKey:@(fieldNumber)]; |
+ ssize_t key = fieldNumber; |
+ GPBExtensionDescriptor *result = |
+ (extensionMap |
+ ? CFDictionaryGetValue(extensionMap, (const void *)key) |
+ : nil); |
+ return result; |
+} |
+ |
+static void CopyKeyValue(const void *key, const void *value, void *context) { |
+ CFMutableDictionaryRef extensionMap = (CFMutableDictionaryRef)context; |
+ CFDictionarySetValue(extensionMap, key, value); |
} |
- (void)addExtensions:(GPBExtensionRegistry *)registry { |
@@ -96,13 +114,18 @@ |
return; |
} |
NSMutableDictionary *otherClassMap = registry->mutableClassMap_; |
- for (Class containingMessageClass in otherClassMap) { |
- NSMutableDictionary *extensionMap = |
+ [otherClassMap enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL * stop) { |
+#pragma unused(stop) |
+ Class containingMessageClass = key; |
+ CFMutableDictionaryRef otherExtensionMap = (CFMutableDictionaryRef)value; |
+ |
+ CFMutableDictionaryRef extensionMap = |
[self extensionMapForContainingMessageClass:containingMessageClass]; |
- NSMutableDictionary *otherExtensionMap = |
- [registry extensionMapForContainingMessageClass:containingMessageClass]; |
- [extensionMap addEntriesFromDictionary:otherExtensionMap]; |
- } |
+ |
+ CFDictionaryApplyFunction(otherExtensionMap, CopyKeyValue, extensionMap); |
+ }]; |
} |
+#pragma clang diagnostic pop |
+ |
@end |