|  | @@ -34,8 +34,6 @@
 | 
	
		
			
				|  |  |  #import "GPBDescriptor.h"
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  @implementation GPBExtensionRegistry {
 | 
	
		
			
				|  |  | -  // TODO(dmaclach): Reimplement with CFDictionaries that don't use
 | 
	
		
			
				|  |  | -  // objects as keys.
 | 
	
		
			
				|  |  |    NSMutableDictionary *mutableClassMap_;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -65,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;
 | 
	
	
		
			
				|  | @@ -83,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 {
 | 
	
	
		
			
				|  | @@ -102,13 +114,16 @@
 | 
	
		
			
				|  |  |      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
 |