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. | |
39 NSMutableDictionary *mutableClassMap_; | 37 NSMutableDictionary *mutableClassMap_; |
40 } | 38 } |
41 | 39 |
42 - (instancetype)init { | 40 - (instancetype)init { |
43 if ((self = [super init])) { | 41 if ((self = [super init])) { |
44 mutableClassMap_ = [[NSMutableDictionary alloc] init]; | 42 mutableClassMap_ = [[NSMutableDictionary alloc] init]; |
45 } | 43 } |
46 return self; | 44 return self; |
47 } | 45 } |
48 | 46 |
49 - (void)dealloc { | 47 - (void)dealloc { |
50 [mutableClassMap_ release]; | 48 [mutableClassMap_ release]; |
51 [super dealloc]; | 49 [super dealloc]; |
52 } | 50 } |
53 | 51 |
| 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 |
54 - (instancetype)copyWithZone:(NSZone *)zone { | 58 - (instancetype)copyWithZone:(NSZone *)zone { |
55 GPBExtensionRegistry *result = [[[self class] allocWithZone:zone] init]; | 59 GPBExtensionRegistry *result = [[[self class] allocWithZone:zone] init]; |
56 if (result && mutableClassMap_.count) { | 60 if (result && mutableClassMap_.count) { |
57 [result->mutableClassMap_ addEntriesFromDictionary:mutableClassMap_]; | 61 [result->mutableClassMap_ addEntriesFromDictionary:mutableClassMap_]; |
58 } | 62 } |
59 return result; | 63 return result; |
60 } | 64 } |
61 | 65 |
62 - (NSMutableDictionary *)extensionMapForContainingMessageClass: | 66 - (CFMutableDictionaryRef)extensionMapForContainingMessageClass: |
63 (Class)containingMessageClass { | 67 (Class)containingMessageClass { |
64 NSMutableDictionary *extensionMap = | 68 CFMutableDictionaryRef extensionMap = (CFMutableDictionaryRef) |
65 [mutableClassMap_ objectForKey:containingMessageClass]; | 69 [mutableClassMap_ objectForKey:containingMessageClass]; |
66 if (extensionMap == nil) { | 70 if (extensionMap == nil) { |
67 extensionMap = [NSMutableDictionary dictionary]; | 71 // Use a custom dictionary here because the keys are numbers and conversion |
68 [mutableClassMap_ setObject:extensionMap | 72 // back and forth from NSNumber isn't worth the cost. |
| 73 extensionMap = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, NULL, |
| 74 &kCFTypeDictionaryValueCallBacks); |
| 75 [mutableClassMap_ setObject:(id)extensionMap |
69 forKey:(id<NSCopying>)containingMessageClass]; | 76 forKey:(id<NSCopying>)containingMessageClass]; |
70 } | 77 } |
71 return extensionMap; | 78 return extensionMap; |
72 } | 79 } |
73 | 80 |
74 - (void)addExtension:(GPBExtensionDescriptor *)extension { | 81 - (void)addExtension:(GPBExtensionDescriptor *)extension { |
75 if (extension == nil) { | 82 if (extension == nil) { |
76 return; | 83 return; |
77 } | 84 } |
78 | 85 |
79 Class containingMessageClass = extension.containingMessageClass; | 86 Class containingMessageClass = extension.containingMessageClass; |
80 NSMutableDictionary *extensionMap = | 87 CFMutableDictionaryRef extensionMap = |
81 [self extensionMapForContainingMessageClass:containingMessageClass]; | 88 [self extensionMapForContainingMessageClass:containingMessageClass]; |
82 [extensionMap setObject:extension forKey:@(extension.fieldNumber)]; | 89 ssize_t key = extension.fieldNumber; |
| 90 CFDictionarySetValue(extensionMap, (const void *)key, extension); |
83 } | 91 } |
84 | 92 |
85 - (GPBExtensionDescriptor *)extensionForDescriptor:(GPBDescriptor *)descriptor | 93 - (GPBExtensionDescriptor *)extensionForDescriptor:(GPBDescriptor *)descriptor |
86 fieldNumber:(NSInteger)fieldNumber { | 94 fieldNumber:(NSInteger)fieldNumber { |
87 Class messageClass = descriptor.messageClass; | 95 Class messageClass = descriptor.messageClass; |
88 NSDictionary *extensionMap = | 96 CFMutableDictionaryRef extensionMap = (CFMutableDictionaryRef) |
89 [mutableClassMap_ objectForKey:messageClass]; | 97 [mutableClassMap_ objectForKey:messageClass]; |
90 return [extensionMap objectForKey:@(fieldNumber)]; | 98 ssize_t key = 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); |
91 } | 109 } |
92 | 110 |
93 - (void)addExtensions:(GPBExtensionRegistry *)registry { | 111 - (void)addExtensions:(GPBExtensionRegistry *)registry { |
94 if (registry == nil) { | 112 if (registry == nil) { |
95 // In the case where there are no extensions just ignore. | 113 // In the case where there are no extensions just ignore. |
96 return; | 114 return; |
97 } | 115 } |
98 NSMutableDictionary *otherClassMap = registry->mutableClassMap_; | 116 NSMutableDictionary *otherClassMap = registry->mutableClassMap_; |
99 for (Class containingMessageClass in otherClassMap) { | 117 [otherClassMap enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL * st
op) { |
100 NSMutableDictionary *extensionMap = | 118 #pragma unused(stop) |
| 119 Class containingMessageClass = key; |
| 120 CFMutableDictionaryRef otherExtensionMap = (CFMutableDictionaryRef)value; |
| 121 |
| 122 CFMutableDictionaryRef extensionMap = |
101 [self extensionMapForContainingMessageClass:containingMessageClass]; | 123 [self extensionMapForContainingMessageClass:containingMessageClass]; |
102 NSMutableDictionary *otherExtensionMap = | 124 |
103 [registry extensionMapForContainingMessageClass:containingMessageClass]; | 125 CFDictionaryApplyFunction(otherExtensionMap, CopyKeyValue, extensionMap); |
104 [extensionMap addEntriesFromDictionary:otherExtensionMap]; | 126 }]; |
105 } | |
106 } | 127 } |
107 | 128 |
| 129 #pragma clang diagnostic pop |
| 130 |
108 @end | 131 @end |
OLD | NEW |