1*6777b538SAndroid Build Coastguard Worker// Protocol Buffers - Google's data interchange format 2*6777b538SAndroid Build Coastguard Worker// Copyright 2008 Google Inc. All rights reserved. 3*6777b538SAndroid Build Coastguard Worker// https://developers.google.com/protocol-buffers/ 4*6777b538SAndroid Build Coastguard Worker// 5*6777b538SAndroid Build Coastguard Worker// Redistribution and use in source and binary forms, with or without 6*6777b538SAndroid Build Coastguard Worker// modification, are permitted provided that the following conditions are 7*6777b538SAndroid Build Coastguard Worker// met: 8*6777b538SAndroid Build Coastguard Worker// 9*6777b538SAndroid Build Coastguard Worker// * Redistributions of source code must retain the above copyright 10*6777b538SAndroid Build Coastguard Worker// notice, this list of conditions and the following disclaimer. 11*6777b538SAndroid Build Coastguard Worker// * Redistributions in binary form must reproduce the above 12*6777b538SAndroid Build Coastguard Worker// copyright notice, this list of conditions and the following disclaimer 13*6777b538SAndroid Build Coastguard Worker// in the documentation and/or other materials provided with the 14*6777b538SAndroid Build Coastguard Worker// distribution. 15*6777b538SAndroid Build Coastguard Worker// * Neither the name of Google Inc. nor the names of its 16*6777b538SAndroid Build Coastguard Worker// contributors may be used to endorse or promote products derived from 17*6777b538SAndroid Build Coastguard Worker// this software without specific prior written permission. 18*6777b538SAndroid Build Coastguard Worker// 19*6777b538SAndroid Build Coastguard Worker// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20*6777b538SAndroid Build Coastguard Worker// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21*6777b538SAndroid Build Coastguard Worker// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22*6777b538SAndroid Build Coastguard Worker// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23*6777b538SAndroid Build Coastguard Worker// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24*6777b538SAndroid Build Coastguard Worker// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25*6777b538SAndroid Build Coastguard Worker// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26*6777b538SAndroid Build Coastguard Worker// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27*6777b538SAndroid Build Coastguard Worker// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28*6777b538SAndroid Build Coastguard Worker// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29*6777b538SAndroid Build Coastguard Worker// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30*6777b538SAndroid Build Coastguard Worker 31*6777b538SAndroid Build Coastguard Worker#import "GPBExtensionRegistry.h" 32*6777b538SAndroid Build Coastguard Worker 33*6777b538SAndroid Build Coastguard Worker#import "GPBBootstrap.h" 34*6777b538SAndroid Build Coastguard Worker#import "GPBDescriptor.h" 35*6777b538SAndroid Build Coastguard Worker 36*6777b538SAndroid Build Coastguard Worker@implementation GPBExtensionRegistry { 37*6777b538SAndroid Build Coastguard Worker CFMutableDictionaryRef mutableClassMap_; 38*6777b538SAndroid Build Coastguard Worker} 39*6777b538SAndroid Build Coastguard Worker 40*6777b538SAndroid Build Coastguard Worker- (instancetype)init { 41*6777b538SAndroid Build Coastguard Worker if ((self = [super init])) { 42*6777b538SAndroid Build Coastguard Worker // The keys are ObjC classes, so straight up ptr comparisons are fine. 43*6777b538SAndroid Build Coastguard Worker mutableClassMap_ = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, NULL, 44*6777b538SAndroid Build Coastguard Worker &kCFTypeDictionaryValueCallBacks); 45*6777b538SAndroid Build Coastguard Worker } 46*6777b538SAndroid Build Coastguard Worker return self; 47*6777b538SAndroid Build Coastguard Worker} 48*6777b538SAndroid Build Coastguard Worker 49*6777b538SAndroid Build Coastguard Worker- (void)dealloc { 50*6777b538SAndroid Build Coastguard Worker CFRelease(mutableClassMap_); 51*6777b538SAndroid Build Coastguard Worker [super dealloc]; 52*6777b538SAndroid Build Coastguard Worker} 53*6777b538SAndroid Build Coastguard Worker 54*6777b538SAndroid Build Coastguard Worker// Direct access is use for speed, to avoid even internally declaring things 55*6777b538SAndroid Build Coastguard Worker// read/write, etc. The warning is enabled in the project to ensure code calling 56*6777b538SAndroid Build Coastguard Worker// protos can turn on -Wdirect-ivar-access without issues. 57*6777b538SAndroid Build Coastguard Worker#pragma clang diagnostic push 58*6777b538SAndroid Build Coastguard Worker#pragma clang diagnostic ignored "-Wdirect-ivar-access" 59*6777b538SAndroid Build Coastguard Worker 60*6777b538SAndroid Build Coastguard Worker- (instancetype)copyWithZone:(NSZone *)zone { 61*6777b538SAndroid Build Coastguard Worker GPBExtensionRegistry *result = [[[self class] allocWithZone:zone] init]; 62*6777b538SAndroid Build Coastguard Worker [result addExtensions:self]; 63*6777b538SAndroid Build Coastguard Worker return result; 64*6777b538SAndroid Build Coastguard Worker} 65*6777b538SAndroid Build Coastguard Worker 66*6777b538SAndroid Build Coastguard Worker- (void)addExtension:(GPBExtensionDescriptor *)extension { 67*6777b538SAndroid Build Coastguard Worker if (extension == nil) { 68*6777b538SAndroid Build Coastguard Worker return; 69*6777b538SAndroid Build Coastguard Worker } 70*6777b538SAndroid Build Coastguard Worker 71*6777b538SAndroid Build Coastguard Worker Class containingMessageClass = extension.containingMessageClass; 72*6777b538SAndroid Build Coastguard Worker CFMutableDictionaryRef extensionMap = (CFMutableDictionaryRef) 73*6777b538SAndroid Build Coastguard Worker CFDictionaryGetValue(mutableClassMap_, containingMessageClass); 74*6777b538SAndroid Build Coastguard Worker if (extensionMap == nil) { 75*6777b538SAndroid Build Coastguard Worker // Use a custom dictionary here because the keys are numbers and conversion 76*6777b538SAndroid Build Coastguard Worker // back and forth from NSNumber isn't worth the cost. 77*6777b538SAndroid Build Coastguard Worker extensionMap = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, NULL, 78*6777b538SAndroid Build Coastguard Worker &kCFTypeDictionaryValueCallBacks); 79*6777b538SAndroid Build Coastguard Worker CFDictionarySetValue(mutableClassMap_, containingMessageClass, extensionMap); 80*6777b538SAndroid Build Coastguard Worker CFRelease(extensionMap); 81*6777b538SAndroid Build Coastguard Worker } 82*6777b538SAndroid Build Coastguard Worker 83*6777b538SAndroid Build Coastguard Worker ssize_t key = extension.fieldNumber; 84*6777b538SAndroid Build Coastguard Worker CFDictionarySetValue(extensionMap, (const void *)key, extension); 85*6777b538SAndroid Build Coastguard Worker} 86*6777b538SAndroid Build Coastguard Worker 87*6777b538SAndroid Build Coastguard Worker- (GPBExtensionDescriptor *)extensionForDescriptor:(GPBDescriptor *)descriptor 88*6777b538SAndroid Build Coastguard Worker fieldNumber:(NSInteger)fieldNumber { 89*6777b538SAndroid Build Coastguard Worker Class messageClass = descriptor.messageClass; 90*6777b538SAndroid Build Coastguard Worker CFMutableDictionaryRef extensionMap = (CFMutableDictionaryRef) 91*6777b538SAndroid Build Coastguard Worker CFDictionaryGetValue(mutableClassMap_, messageClass); 92*6777b538SAndroid Build Coastguard Worker ssize_t key = fieldNumber; 93*6777b538SAndroid Build Coastguard Worker GPBExtensionDescriptor *result = 94*6777b538SAndroid Build Coastguard Worker (extensionMap 95*6777b538SAndroid Build Coastguard Worker ? CFDictionaryGetValue(extensionMap, (const void *)key) 96*6777b538SAndroid Build Coastguard Worker : nil); 97*6777b538SAndroid Build Coastguard Worker return result; 98*6777b538SAndroid Build Coastguard Worker} 99*6777b538SAndroid Build Coastguard Worker 100*6777b538SAndroid Build Coastguard Workerstatic void CopyKeyValue(const void *key, const void *value, void *context) { 101*6777b538SAndroid Build Coastguard Worker CFMutableDictionaryRef extensionMap = (CFMutableDictionaryRef)context; 102*6777b538SAndroid Build Coastguard Worker CFDictionarySetValue(extensionMap, key, value); 103*6777b538SAndroid Build Coastguard Worker} 104*6777b538SAndroid Build Coastguard Worker 105*6777b538SAndroid Build Coastguard Workerstatic void CopySubDictionary(const void *key, const void *value, void *context) { 106*6777b538SAndroid Build Coastguard Worker CFMutableDictionaryRef mutableClassMap = (CFMutableDictionaryRef)context; 107*6777b538SAndroid Build Coastguard Worker Class containingMessageClass = key; 108*6777b538SAndroid Build Coastguard Worker CFMutableDictionaryRef otherExtensionMap = (CFMutableDictionaryRef)value; 109*6777b538SAndroid Build Coastguard Worker 110*6777b538SAndroid Build Coastguard Worker CFMutableDictionaryRef extensionMap = (CFMutableDictionaryRef) 111*6777b538SAndroid Build Coastguard Worker CFDictionaryGetValue(mutableClassMap, containingMessageClass); 112*6777b538SAndroid Build Coastguard Worker if (extensionMap == nil) { 113*6777b538SAndroid Build Coastguard Worker extensionMap = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, otherExtensionMap); 114*6777b538SAndroid Build Coastguard Worker CFDictionarySetValue(mutableClassMap, containingMessageClass, extensionMap); 115*6777b538SAndroid Build Coastguard Worker CFRelease(extensionMap); 116*6777b538SAndroid Build Coastguard Worker } else { 117*6777b538SAndroid Build Coastguard Worker CFDictionaryApplyFunction(otherExtensionMap, CopyKeyValue, extensionMap); 118*6777b538SAndroid Build Coastguard Worker } 119*6777b538SAndroid Build Coastguard Worker} 120*6777b538SAndroid Build Coastguard Worker 121*6777b538SAndroid Build Coastguard Worker- (void)addExtensions:(GPBExtensionRegistry *)registry { 122*6777b538SAndroid Build Coastguard Worker if (registry == nil) { 123*6777b538SAndroid Build Coastguard Worker // In the case where there are no extensions just ignore. 124*6777b538SAndroid Build Coastguard Worker return; 125*6777b538SAndroid Build Coastguard Worker } 126*6777b538SAndroid Build Coastguard Worker CFDictionaryApplyFunction(registry->mutableClassMap_, CopySubDictionary, mutableClassMap_); 127*6777b538SAndroid Build Coastguard Worker} 128*6777b538SAndroid Build Coastguard Worker 129*6777b538SAndroid Build Coastguard Worker#pragma clang diagnostic pop 130*6777b538SAndroid Build Coastguard Worker 131*6777b538SAndroid Build Coastguard Worker@end 132