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