1// Protocol Buffers - Google's data interchange format 2// Copyright 2008 Google Inc. All rights reserved. 3// https://developers.google.com/protocol-buffers/ 4// 5// Redistribution and use in source and binary forms, with or without 6// modification, are permitted provided that the following conditions are 7// met: 8// 9// * Redistributions of source code must retain the above copyright 10// notice, this list of conditions and the following disclaimer. 11// * Redistributions in binary form must reproduce the above 12// copyright notice, this list of conditions and the following disclaimer 13// in the documentation and/or other materials provided with the 14// distribution. 15// * Neither the name of Google Inc. nor the names of its 16// contributors may be used to endorse or promote products derived from 17// this software without specific prior written permission. 18// 19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 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. 30 31#import "GPBExtensionRegistry.h" 32 33#import "GPBBootstrap.h" 34#import "GPBDescriptor.h" 35 36@implementation GPBExtensionRegistry { 37 // TODO(dmaclach): Reimplement with CFDictionaries that don't use 38 // objects as keys. 39 NSMutableDictionary *mutableClassMap_; 40} 41 42- (instancetype)init { 43 if ((self = [super init])) { 44 mutableClassMap_ = [[NSMutableDictionary alloc] init]; 45 } 46 return self; 47} 48 49- (void)dealloc { 50 [mutableClassMap_ release]; 51 [super dealloc]; 52} 53 54// Direct access is use for speed, to avoid even internally declaring things 55// read/write, etc. The warning is enabled in the project to ensure code calling 56// protos can turn on -Wdirect-ivar-access without issues. 57#pragma clang diagnostic push 58#pragma clang diagnostic ignored "-Wdirect-ivar-access" 59 60- (instancetype)copyWithZone:(NSZone *)zone { 61 GPBExtensionRegistry *result = [[[self class] allocWithZone:zone] init]; 62 if (result && mutableClassMap_.count) { 63 [result->mutableClassMap_ addEntriesFromDictionary:mutableClassMap_]; 64 } 65 return result; 66} 67 68- (NSMutableDictionary *)extensionMapForContainingMessageClass: 69 (Class)containingMessageClass { 70 NSMutableDictionary *extensionMap = 71 [mutableClassMap_ objectForKey:containingMessageClass]; 72 if (extensionMap == nil) { 73 extensionMap = [NSMutableDictionary dictionary]; 74 [mutableClassMap_ setObject:extensionMap 75 forKey:(id<NSCopying>)containingMessageClass]; 76 } 77 return extensionMap; 78} 79 80- (void)addExtension:(GPBExtensionDescriptor *)extension { 81 if (extension == nil) { 82 return; 83 } 84 85 Class containingMessageClass = extension.containingMessageClass; 86 NSMutableDictionary *extensionMap = 87 [self extensionMapForContainingMessageClass:containingMessageClass]; 88 [extensionMap setObject:extension forKey:@(extension.fieldNumber)]; 89} 90 91- (GPBExtensionDescriptor *)extensionForDescriptor:(GPBDescriptor *)descriptor 92 fieldNumber:(NSInteger)fieldNumber { 93 Class messageClass = descriptor.messageClass; 94 NSDictionary *extensionMap = 95 [mutableClassMap_ objectForKey:messageClass]; 96 return [extensionMap objectForKey:@(fieldNumber)]; 97} 98 99- (void)addExtensions:(GPBExtensionRegistry *)registry { 100 if (registry == nil) { 101 // In the case where there are no extensions just ignore. 102 return; 103 } 104 NSMutableDictionary *otherClassMap = registry->mutableClassMap_; 105 for (Class containingMessageClass in otherClassMap) { 106 NSMutableDictionary *extensionMap = 107 [self extensionMapForContainingMessageClass:containingMessageClass]; 108 NSMutableDictionary *otherExtensionMap = 109 [registry extensionMapForContainingMessageClass:containingMessageClass]; 110 [extensionMap addEntriesFromDictionary:otherExtensionMap]; 111 } 112} 113 114#pragma clang diagnostic pop 115 116@end 117