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 |