| OLD | NEW |
| 1 // Protocol Buffers - Google's data interchange format | 1 // Protocol Buffers - Google's data interchange format |
| 2 // Copyright 2008 Google Inc. All rights reserved. | 2 // Copyright 2008 Google Inc. All rights reserved. |
| 3 // https://developers.google.com/protocol-buffers/ | 3 // https://developers.google.com/protocol-buffers/ |
| 4 // | 4 // |
| 5 // Redistribution and use in source and binary forms, with or without | 5 // Redistribution and use in source and binary forms, with or without |
| 6 // modification, are permitted provided that the following conditions are | 6 // modification, are permitted provided that the following conditions are |
| 7 // met: | 7 // met: |
| 8 // | 8 // |
| 9 // * Redistributions of source code must retain the above copyright | 9 // * Redistributions of source code must retain the above copyright |
| 10 // notice, this list of conditions and the following disclaimer. | 10 // notice, this list of conditions and the following disclaimer. |
| (...skipping 16 matching lines...) Expand all Loading... |
| 27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 30 | 30 |
| 31 #import "GPBExtensionRegistry.h" | 31 #import "GPBExtensionRegistry.h" |
| 32 | 32 |
| 33 #import "GPBBootstrap.h" | 33 #import "GPBBootstrap.h" |
| 34 #import "GPBDescriptor.h" | 34 #import "GPBDescriptor.h" |
| 35 | 35 |
| 36 @implementation GPBExtensionRegistry { | 36 @implementation GPBExtensionRegistry { |
| 37 // TODO(dmaclach): Reimplement with CFDictionaries that don't use |
| 38 // objects as keys. |
| 37 NSMutableDictionary *mutableClassMap_; | 39 NSMutableDictionary *mutableClassMap_; |
| 38 } | 40 } |
| 39 | 41 |
| 40 - (instancetype)init { | 42 - (instancetype)init { |
| 41 if ((self = [super init])) { | 43 if ((self = [super init])) { |
| 42 mutableClassMap_ = [[NSMutableDictionary alloc] init]; | 44 mutableClassMap_ = [[NSMutableDictionary alloc] init]; |
| 43 } | 45 } |
| 44 return self; | 46 return self; |
| 45 } | 47 } |
| 46 | 48 |
| 47 - (void)dealloc { | 49 - (void)dealloc { |
| 48 [mutableClassMap_ release]; | 50 [mutableClassMap_ release]; |
| 49 [super dealloc]; | 51 [super dealloc]; |
| 50 } | 52 } |
| 51 | 53 |
| 52 // Direct access is use for speed, to avoid even internally declaring things | |
| 53 // read/write, etc. The warning is enabled in the project to ensure code calling | |
| 54 // protos can turn on -Wdirect-ivar-access without issues. | |
| 55 #pragma clang diagnostic push | |
| 56 #pragma clang diagnostic ignored "-Wdirect-ivar-access" | |
| 57 | |
| 58 - (instancetype)copyWithZone:(NSZone *)zone { | 54 - (instancetype)copyWithZone:(NSZone *)zone { |
| 59 GPBExtensionRegistry *result = [[[self class] allocWithZone:zone] init]; | 55 GPBExtensionRegistry *result = [[[self class] allocWithZone:zone] init]; |
| 60 if (result && mutableClassMap_.count) { | 56 if (result && mutableClassMap_.count) { |
| 61 [result->mutableClassMap_ addEntriesFromDictionary:mutableClassMap_]; | 57 [result->mutableClassMap_ addEntriesFromDictionary:mutableClassMap_]; |
| 62 } | 58 } |
| 63 return result; | 59 return result; |
| 64 } | 60 } |
| 65 | 61 |
| 66 - (CFMutableDictionaryRef)extensionMapForContainingMessageClass: | 62 - (NSMutableDictionary *)extensionMapForContainingMessageClass: |
| 67 (Class)containingMessageClass { | 63 (Class)containingMessageClass { |
| 68 CFMutableDictionaryRef extensionMap = (CFMutableDictionaryRef) | 64 NSMutableDictionary *extensionMap = |
| 69 [mutableClassMap_ objectForKey:containingMessageClass]; | 65 [mutableClassMap_ objectForKey:containingMessageClass]; |
| 70 if (extensionMap == nil) { | 66 if (extensionMap == nil) { |
| 71 // Use a custom dictionary here because the keys are numbers and conversion | 67 extensionMap = [NSMutableDictionary dictionary]; |
| 72 // back and forth from NSNumber isn't worth the cost. | 68 [mutableClassMap_ setObject:extensionMap |
| 73 extensionMap = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, NULL, | |
| 74 &kCFTypeDictionaryValueCallBacks); | |
| 75 [mutableClassMap_ setObject:(id)extensionMap | |
| 76 forKey:(id<NSCopying>)containingMessageClass]; | 69 forKey:(id<NSCopying>)containingMessageClass]; |
| 77 } | 70 } |
| 78 return extensionMap; | 71 return extensionMap; |
| 79 } | 72 } |
| 80 | 73 |
| 81 - (void)addExtension:(GPBExtensionDescriptor *)extension { | 74 - (void)addExtension:(GPBExtensionDescriptor *)extension { |
| 82 if (extension == nil) { | 75 if (extension == nil) { |
| 83 return; | 76 return; |
| 84 } | 77 } |
| 85 | 78 |
| 86 Class containingMessageClass = extension.containingMessageClass; | 79 Class containingMessageClass = extension.containingMessageClass; |
| 87 CFMutableDictionaryRef extensionMap = | 80 NSMutableDictionary *extensionMap = |
| 88 [self extensionMapForContainingMessageClass:containingMessageClass]; | 81 [self extensionMapForContainingMessageClass:containingMessageClass]; |
| 89 ssize_t key = extension.fieldNumber; | 82 [extensionMap setObject:extension forKey:@(extension.fieldNumber)]; |
| 90 CFDictionarySetValue(extensionMap, (const void *)key, extension); | |
| 91 } | 83 } |
| 92 | 84 |
| 93 - (GPBExtensionDescriptor *)extensionForDescriptor:(GPBDescriptor *)descriptor | 85 - (GPBExtensionDescriptor *)extensionForDescriptor:(GPBDescriptor *)descriptor |
| 94 fieldNumber:(NSInteger)fieldNumber { | 86 fieldNumber:(NSInteger)fieldNumber { |
| 95 Class messageClass = descriptor.messageClass; | 87 Class messageClass = descriptor.messageClass; |
| 96 CFMutableDictionaryRef extensionMap = (CFMutableDictionaryRef) | 88 NSDictionary *extensionMap = |
| 97 [mutableClassMap_ objectForKey:messageClass]; | 89 [mutableClassMap_ objectForKey:messageClass]; |
| 98 ssize_t key = fieldNumber; | 90 return [extensionMap objectForKey:@(fieldNumber)]; |
| 99 GPBExtensionDescriptor *result = | |
| 100 (extensionMap | |
| 101 ? CFDictionaryGetValue(extensionMap, (const void *)key) | |
| 102 : nil); | |
| 103 return result; | |
| 104 } | |
| 105 | |
| 106 static void CopyKeyValue(const void *key, const void *value, void *context) { | |
| 107 CFMutableDictionaryRef extensionMap = (CFMutableDictionaryRef)context; | |
| 108 CFDictionarySetValue(extensionMap, key, value); | |
| 109 } | 91 } |
| 110 | 92 |
| 111 - (void)addExtensions:(GPBExtensionRegistry *)registry { | 93 - (void)addExtensions:(GPBExtensionRegistry *)registry { |
| 112 if (registry == nil) { | 94 if (registry == nil) { |
| 113 // In the case where there are no extensions just ignore. | 95 // In the case where there are no extensions just ignore. |
| 114 return; | 96 return; |
| 115 } | 97 } |
| 116 NSMutableDictionary *otherClassMap = registry->mutableClassMap_; | 98 NSMutableDictionary *otherClassMap = registry->mutableClassMap_; |
| 117 [otherClassMap enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL * st
op) { | 99 for (Class containingMessageClass in otherClassMap) { |
| 118 #pragma unused(stop) | 100 NSMutableDictionary *extensionMap = |
| 119 Class containingMessageClass = key; | |
| 120 CFMutableDictionaryRef otherExtensionMap = (CFMutableDictionaryRef)value; | |
| 121 | |
| 122 CFMutableDictionaryRef extensionMap = | |
| 123 [self extensionMapForContainingMessageClass:containingMessageClass]; | 101 [self extensionMapForContainingMessageClass:containingMessageClass]; |
| 124 | 102 NSMutableDictionary *otherExtensionMap = |
| 125 CFDictionaryApplyFunction(otherExtensionMap, CopyKeyValue, extensionMap); | 103 [registry extensionMapForContainingMessageClass:containingMessageClass]; |
| 126 }]; | 104 [extensionMap addEntriesFromDictionary:otherExtensionMap]; |
| 105 } |
| 127 } | 106 } |
| 128 | 107 |
| 129 #pragma clang diagnostic pop | |
| 130 | |
| 131 @end | 108 @end |
| OLD | NEW |