diff --git a/objectivec/GPBExtensionRegistry.m b/objectivec/GPBExtensionRegistry.m index 65534b67..01eb761f 100644 --- a/objectivec/GPBExtensionRegistry.m +++ b/objectivec/GPBExtensionRegistry.m @@ -34,6 +34,8 @@ #import "GPBDescriptor.h" @implementation GPBExtensionRegistry { + // TODO(dmaclach): Reimplement with CFDictionaries that don't use + // objects as keys. NSMutableDictionary *mutableClassMap_; } @@ -63,16 +65,13 @@ return result; } -- (CFMutableDictionaryRef)extensionMapForContainingMessageClass: +- (NSMutableDictionary *)extensionMapForContainingMessageClass: (Class)containingMessageClass { - CFMutableDictionaryRef extensionMap = (CFMutableDictionaryRef) + NSMutableDictionary *extensionMap = [mutableClassMap_ objectForKey:containingMessageClass]; if (extensionMap == nil) { - // 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 + extensionMap = [NSMutableDictionary dictionary]; + [mutableClassMap_ setObject:extensionMap forKey:(id)containingMessageClass]; } return extensionMap; @@ -84,28 +83,17 @@ } Class containingMessageClass = extension.containingMessageClass; - CFMutableDictionaryRef extensionMap = + NSMutableDictionary *extensionMap = [self extensionMapForContainingMessageClass:containingMessageClass]; - ssize_t key = extension.fieldNumber; - CFDictionarySetValue(extensionMap, (const void *)key, extension); + [extensionMap setObject:extension forKey:@(extension.fieldNumber)]; } - (GPBExtensionDescriptor *)extensionForDescriptor:(GPBDescriptor *)descriptor fieldNumber:(NSInteger)fieldNumber { Class messageClass = descriptor.messageClass; - CFMutableDictionaryRef extensionMap = (CFMutableDictionaryRef) + NSDictionary *extensionMap = [mutableClassMap_ objectForKey:messageClass]; - 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); + return [extensionMap objectForKey:@(fieldNumber)]; } - (void)addExtensions:(GPBExtensionRegistry *)registry { @@ -114,16 +102,13 @@ static void CopyKeyValue(const void *key, const void *value, void *context) { return; } NSMutableDictionary *otherClassMap = registry->mutableClassMap_; - [otherClassMap enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL * stop) { -#pragma unused(stop) - Class containingMessageClass = key; - CFMutableDictionaryRef otherExtensionMap = (CFMutableDictionaryRef)value; - - CFMutableDictionaryRef extensionMap = + for (Class containingMessageClass in otherClassMap) { + NSMutableDictionary *extensionMap = [self extensionMapForContainingMessageClass:containingMessageClass]; - - CFDictionaryApplyFunction(otherExtensionMap, CopyKeyValue, extensionMap); - }]; + NSMutableDictionary *otherExtensionMap = + [registry extensionMapForContainingMessageClass:containingMessageClass]; + [extensionMap addEntriesFromDictionary:otherExtensionMap]; + } } #pragma clang diagnostic pop diff --git a/objectivec/GPBUnknownFieldSet.m b/objectivec/GPBUnknownFieldSet.m index a7335f05..9ba1d65c 100644 --- a/objectivec/GPBUnknownFieldSet.m +++ b/objectivec/GPBUnknownFieldSet.m @@ -36,6 +36,39 @@ #import "GPBUtilities.h" #import "GPBWireFormat.h" +#pragma mark CFDictionaryKeyCallBacks + +// We use a custom dictionary here because our keys are numbers and +// conversion back and forth from NSNumber was costing us performance. +// If/when we move to C++ this could be done using a std::map and some +// careful retain/release calls. + +static const void *GPBUnknownFieldSetKeyRetain(CFAllocatorRef allocator, + const void *value) { +#pragma unused(allocator) + return value; +} + +static void GPBUnknownFieldSetKeyRelease(CFAllocatorRef allocator, + const void *value) { +#pragma unused(allocator) +#pragma unused(value) +} + +static CFStringRef GPBUnknownFieldSetCopyKeyDescription(const void *value) { + return CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%d"), + (int)value); +} + +static Boolean GPBUnknownFieldSetKeyEqual(const void *value1, + const void *value2) { + return value1 == value2; +} + +static CFHashCode GPBUnknownFieldSetKeyHash(const void *value) { + return (CFHashCode)value; +} + #pragma mark Helpers static void checkNumber(int32_t number) { @@ -258,9 +291,13 @@ static void GPBUnknownFieldSetSerializedSizeAsMessageSet(const void *key, int32_t number = [field number]; checkNumber(number); if (!fields_) { - // Use a custom dictionary here because the keys are numbers and conversion - // back and forth from NSNumber isn't worth the cost. - fields_ = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, NULL, + CFDictionaryKeyCallBacks keyCallBacks = { + // See description above for reason for using custom dictionary. + 0, GPBUnknownFieldSetKeyRetain, GPBUnknownFieldSetKeyRelease, + GPBUnknownFieldSetCopyKeyDescription, GPBUnknownFieldSetKeyEqual, + GPBUnknownFieldSetKeyHash, + }; + fields_ = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &keyCallBacks, &kCFTypeDictionaryValueCallBacks); } ssize_t key = number;