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 "GPBMessage_PackagePrivate.h" 32*1b3f573fSAndroid Build Coastguard Worker 33*1b3f573fSAndroid Build Coastguard Worker#import <objc/runtime.h> 34*1b3f573fSAndroid Build Coastguard Worker#import <objc/message.h> 35*1b3f573fSAndroid Build Coastguard Worker#import <stdatomic.h> 36*1b3f573fSAndroid Build Coastguard Worker 37*1b3f573fSAndroid Build Coastguard Worker#import "GPBArray_PackagePrivate.h" 38*1b3f573fSAndroid Build Coastguard Worker#import "GPBCodedInputStream_PackagePrivate.h" 39*1b3f573fSAndroid Build Coastguard Worker#import "GPBCodedOutputStream_PackagePrivate.h" 40*1b3f573fSAndroid Build Coastguard Worker#import "GPBDescriptor_PackagePrivate.h" 41*1b3f573fSAndroid Build Coastguard Worker#import "GPBDictionary_PackagePrivate.h" 42*1b3f573fSAndroid Build Coastguard Worker#import "GPBExtensionInternals.h" 43*1b3f573fSAndroid Build Coastguard Worker#import "GPBExtensionRegistry.h" 44*1b3f573fSAndroid Build Coastguard Worker#import "GPBRootObject_PackagePrivate.h" 45*1b3f573fSAndroid Build Coastguard Worker#import "GPBUnknownFieldSet_PackagePrivate.h" 46*1b3f573fSAndroid Build Coastguard Worker#import "GPBUtilities_PackagePrivate.h" 47*1b3f573fSAndroid Build Coastguard Worker 48*1b3f573fSAndroid Build Coastguard Worker// Direct access is use for speed, to avoid even internally declaring things 49*1b3f573fSAndroid Build Coastguard Worker// read/write, etc. The warning is enabled in the project to ensure code calling 50*1b3f573fSAndroid Build Coastguard Worker// protos can turn on -Wdirect-ivar-access without issues. 51*1b3f573fSAndroid Build Coastguard Worker#pragma clang diagnostic push 52*1b3f573fSAndroid Build Coastguard Worker#pragma clang diagnostic ignored "-Wdirect-ivar-access" 53*1b3f573fSAndroid Build Coastguard Worker 54*1b3f573fSAndroid Build Coastguard WorkerNSString *const GPBMessageErrorDomain = 55*1b3f573fSAndroid Build Coastguard Worker GPBNSStringifySymbol(GPBMessageErrorDomain); 56*1b3f573fSAndroid Build Coastguard Worker 57*1b3f573fSAndroid Build Coastguard WorkerNSString *const GPBErrorReasonKey = @"Reason"; 58*1b3f573fSAndroid Build Coastguard Worker 59*1b3f573fSAndroid Build Coastguard Workerstatic NSString *const kGPBDataCoderKey = @"GPBData"; 60*1b3f573fSAndroid Build Coastguard Worker 61*1b3f573fSAndroid Build Coastguard Worker// 62*1b3f573fSAndroid Build Coastguard Worker// PLEASE REMEMBER: 63*1b3f573fSAndroid Build Coastguard Worker// 64*1b3f573fSAndroid Build Coastguard Worker// This is the base class for *all* messages generated, so any selector defined, 65*1b3f573fSAndroid Build Coastguard Worker// *public* or *private* could end up colliding with a proto message field. So 66*1b3f573fSAndroid Build Coastguard Worker// avoid using selectors that could match a property, use C functions to hide 67*1b3f573fSAndroid Build Coastguard Worker// them, etc. 68*1b3f573fSAndroid Build Coastguard Worker// 69*1b3f573fSAndroid Build Coastguard Worker 70*1b3f573fSAndroid Build Coastguard Worker@interface GPBMessage () { 71*1b3f573fSAndroid Build Coastguard Worker @package 72*1b3f573fSAndroid Build Coastguard Worker GPBUnknownFieldSet *unknownFields_; 73*1b3f573fSAndroid Build Coastguard Worker NSMutableDictionary *extensionMap_; 74*1b3f573fSAndroid Build Coastguard Worker // Readonly access to autocreatedExtensionMap_ is protected via 75*1b3f573fSAndroid Build Coastguard Worker // readOnlySemaphore_. 76*1b3f573fSAndroid Build Coastguard Worker NSMutableDictionary *autocreatedExtensionMap_; 77*1b3f573fSAndroid Build Coastguard Worker 78*1b3f573fSAndroid Build Coastguard Worker // If the object was autocreated, we remember the creator so that if we get 79*1b3f573fSAndroid Build Coastguard Worker // mutated, we can inform the creator to make our field visible. 80*1b3f573fSAndroid Build Coastguard Worker GPBMessage *autocreator_; 81*1b3f573fSAndroid Build Coastguard Worker GPBFieldDescriptor *autocreatorField_; 82*1b3f573fSAndroid Build Coastguard Worker GPBExtensionDescriptor *autocreatorExtension_; 83*1b3f573fSAndroid Build Coastguard Worker 84*1b3f573fSAndroid Build Coastguard Worker // Message can only be mutated from one thread. But some *readonly* operations 85*1b3f573fSAndroid Build Coastguard Worker // modify internal state because they autocreate things. The 86*1b3f573fSAndroid Build Coastguard Worker // autocreatedExtensionMap_ is one such structure. Access during readonly 87*1b3f573fSAndroid Build Coastguard Worker // operations is protected via this semaphore. 88*1b3f573fSAndroid Build Coastguard Worker // NOTE: OSSpinLock may seem like a good fit here but Apple engineers have 89*1b3f573fSAndroid Build Coastguard Worker // pointed out that they are vulnerable to live locking on iOS in cases of 90*1b3f573fSAndroid Build Coastguard Worker // priority inversion: 91*1b3f573fSAndroid Build Coastguard Worker // http://mjtsai.com/blog/2015/12/16/osspinlock-is-unsafe/ 92*1b3f573fSAndroid Build Coastguard Worker // https://lists.swift.org/pipermail/swift-dev/Week-of-Mon-20151214/000372.html 93*1b3f573fSAndroid Build Coastguard Worker // Use of readOnlySemaphore_ must be prefaced by a call to 94*1b3f573fSAndroid Build Coastguard Worker // GPBPrepareReadOnlySemaphore to ensure it has been created. This allows 95*1b3f573fSAndroid Build Coastguard Worker // readOnlySemaphore_ to be only created when actually needed. 96*1b3f573fSAndroid Build Coastguard Worker _Atomic(dispatch_semaphore_t) readOnlySemaphore_; 97*1b3f573fSAndroid Build Coastguard Worker} 98*1b3f573fSAndroid Build Coastguard Worker@end 99*1b3f573fSAndroid Build Coastguard Worker 100*1b3f573fSAndroid Build Coastguard Workerstatic id CreateArrayForField(GPBFieldDescriptor *field, 101*1b3f573fSAndroid Build Coastguard Worker GPBMessage *autocreator) 102*1b3f573fSAndroid Build Coastguard Worker __attribute__((ns_returns_retained)); 103*1b3f573fSAndroid Build Coastguard Workerstatic id GetOrCreateArrayIvarWithField(GPBMessage *self, 104*1b3f573fSAndroid Build Coastguard Worker GPBFieldDescriptor *field); 105*1b3f573fSAndroid Build Coastguard Workerstatic id GetArrayIvarWithField(GPBMessage *self, GPBFieldDescriptor *field); 106*1b3f573fSAndroid Build Coastguard Workerstatic id CreateMapForField(GPBFieldDescriptor *field, 107*1b3f573fSAndroid Build Coastguard Worker GPBMessage *autocreator) 108*1b3f573fSAndroid Build Coastguard Worker __attribute__((ns_returns_retained)); 109*1b3f573fSAndroid Build Coastguard Workerstatic id GetOrCreateMapIvarWithField(GPBMessage *self, 110*1b3f573fSAndroid Build Coastguard Worker GPBFieldDescriptor *field); 111*1b3f573fSAndroid Build Coastguard Workerstatic id GetMapIvarWithField(GPBMessage *self, GPBFieldDescriptor *field); 112*1b3f573fSAndroid Build Coastguard Workerstatic NSMutableDictionary *CloneExtensionMap(NSDictionary *extensionMap, 113*1b3f573fSAndroid Build Coastguard Worker NSZone *zone) 114*1b3f573fSAndroid Build Coastguard Worker __attribute__((ns_returns_retained)); 115*1b3f573fSAndroid Build Coastguard Worker 116*1b3f573fSAndroid Build Coastguard Worker#ifdef DEBUG 117*1b3f573fSAndroid Build Coastguard Workerstatic NSError *MessageError(NSInteger code, NSDictionary *userInfo) { 118*1b3f573fSAndroid Build Coastguard Worker return [NSError errorWithDomain:GPBMessageErrorDomain 119*1b3f573fSAndroid Build Coastguard Worker code:code 120*1b3f573fSAndroid Build Coastguard Worker userInfo:userInfo]; 121*1b3f573fSAndroid Build Coastguard Worker} 122*1b3f573fSAndroid Build Coastguard Worker#endif 123*1b3f573fSAndroid Build Coastguard Worker 124*1b3f573fSAndroid Build Coastguard Workerstatic NSError *ErrorFromException(NSException *exception) { 125*1b3f573fSAndroid Build Coastguard Worker NSError *error = nil; 126*1b3f573fSAndroid Build Coastguard Worker 127*1b3f573fSAndroid Build Coastguard Worker if ([exception.name isEqual:GPBCodedInputStreamException]) { 128*1b3f573fSAndroid Build Coastguard Worker NSDictionary *exceptionInfo = exception.userInfo; 129*1b3f573fSAndroid Build Coastguard Worker error = exceptionInfo[GPBCodedInputStreamUnderlyingErrorKey]; 130*1b3f573fSAndroid Build Coastguard Worker } 131*1b3f573fSAndroid Build Coastguard Worker 132*1b3f573fSAndroid Build Coastguard Worker if (!error) { 133*1b3f573fSAndroid Build Coastguard Worker NSString *reason = exception.reason; 134*1b3f573fSAndroid Build Coastguard Worker NSDictionary *userInfo = nil; 135*1b3f573fSAndroid Build Coastguard Worker if ([reason length]) { 136*1b3f573fSAndroid Build Coastguard Worker userInfo = @{ GPBErrorReasonKey : reason }; 137*1b3f573fSAndroid Build Coastguard Worker } 138*1b3f573fSAndroid Build Coastguard Worker 139*1b3f573fSAndroid Build Coastguard Worker error = [NSError errorWithDomain:GPBMessageErrorDomain 140*1b3f573fSAndroid Build Coastguard Worker code:GPBMessageErrorCodeOther 141*1b3f573fSAndroid Build Coastguard Worker userInfo:userInfo]; 142*1b3f573fSAndroid Build Coastguard Worker } 143*1b3f573fSAndroid Build Coastguard Worker return error; 144*1b3f573fSAndroid Build Coastguard Worker} 145*1b3f573fSAndroid Build Coastguard Worker 146*1b3f573fSAndroid Build Coastguard Workerstatic void CheckExtension(GPBMessage *self, 147*1b3f573fSAndroid Build Coastguard Worker GPBExtensionDescriptor *extension) { 148*1b3f573fSAndroid Build Coastguard Worker if (![self isKindOfClass:extension.containingMessageClass]) { 149*1b3f573fSAndroid Build Coastguard Worker [NSException 150*1b3f573fSAndroid Build Coastguard Worker raise:NSInvalidArgumentException 151*1b3f573fSAndroid Build Coastguard Worker format:@"Extension %@ used on wrong class (%@ instead of %@)", 152*1b3f573fSAndroid Build Coastguard Worker extension.singletonName, 153*1b3f573fSAndroid Build Coastguard Worker [self class], extension.containingMessageClass]; 154*1b3f573fSAndroid Build Coastguard Worker } 155*1b3f573fSAndroid Build Coastguard Worker} 156*1b3f573fSAndroid Build Coastguard Worker 157*1b3f573fSAndroid Build Coastguard Workerstatic NSMutableDictionary *CloneExtensionMap(NSDictionary *extensionMap, 158*1b3f573fSAndroid Build Coastguard Worker NSZone *zone) { 159*1b3f573fSAndroid Build Coastguard Worker if (extensionMap.count == 0) { 160*1b3f573fSAndroid Build Coastguard Worker return nil; 161*1b3f573fSAndroid Build Coastguard Worker } 162*1b3f573fSAndroid Build Coastguard Worker NSMutableDictionary *result = [[NSMutableDictionary allocWithZone:zone] 163*1b3f573fSAndroid Build Coastguard Worker initWithCapacity:extensionMap.count]; 164*1b3f573fSAndroid Build Coastguard Worker 165*1b3f573fSAndroid Build Coastguard Worker for (GPBExtensionDescriptor *extension in extensionMap) { 166*1b3f573fSAndroid Build Coastguard Worker id value = [extensionMap objectForKey:extension]; 167*1b3f573fSAndroid Build Coastguard Worker BOOL isMessageExtension = GPBExtensionIsMessage(extension); 168*1b3f573fSAndroid Build Coastguard Worker 169*1b3f573fSAndroid Build Coastguard Worker if (extension.repeated) { 170*1b3f573fSAndroid Build Coastguard Worker if (isMessageExtension) { 171*1b3f573fSAndroid Build Coastguard Worker NSMutableArray *list = 172*1b3f573fSAndroid Build Coastguard Worker [[NSMutableArray alloc] initWithCapacity:[value count]]; 173*1b3f573fSAndroid Build Coastguard Worker for (GPBMessage *listValue in value) { 174*1b3f573fSAndroid Build Coastguard Worker GPBMessage *copiedValue = [listValue copyWithZone:zone]; 175*1b3f573fSAndroid Build Coastguard Worker [list addObject:copiedValue]; 176*1b3f573fSAndroid Build Coastguard Worker [copiedValue release]; 177*1b3f573fSAndroid Build Coastguard Worker } 178*1b3f573fSAndroid Build Coastguard Worker [result setObject:list forKey:extension]; 179*1b3f573fSAndroid Build Coastguard Worker [list release]; 180*1b3f573fSAndroid Build Coastguard Worker } else { 181*1b3f573fSAndroid Build Coastguard Worker NSMutableArray *copiedValue = [value mutableCopyWithZone:zone]; 182*1b3f573fSAndroid Build Coastguard Worker [result setObject:copiedValue forKey:extension]; 183*1b3f573fSAndroid Build Coastguard Worker [copiedValue release]; 184*1b3f573fSAndroid Build Coastguard Worker } 185*1b3f573fSAndroid Build Coastguard Worker } else { 186*1b3f573fSAndroid Build Coastguard Worker if (isMessageExtension) { 187*1b3f573fSAndroid Build Coastguard Worker GPBMessage *copiedValue = [value copyWithZone:zone]; 188*1b3f573fSAndroid Build Coastguard Worker [result setObject:copiedValue forKey:extension]; 189*1b3f573fSAndroid Build Coastguard Worker [copiedValue release]; 190*1b3f573fSAndroid Build Coastguard Worker } else { 191*1b3f573fSAndroid Build Coastguard Worker [result setObject:value forKey:extension]; 192*1b3f573fSAndroid Build Coastguard Worker } 193*1b3f573fSAndroid Build Coastguard Worker } 194*1b3f573fSAndroid Build Coastguard Worker } 195*1b3f573fSAndroid Build Coastguard Worker 196*1b3f573fSAndroid Build Coastguard Worker return result; 197*1b3f573fSAndroid Build Coastguard Worker} 198*1b3f573fSAndroid Build Coastguard Worker 199*1b3f573fSAndroid Build Coastguard Workerstatic id CreateArrayForField(GPBFieldDescriptor *field, 200*1b3f573fSAndroid Build Coastguard Worker GPBMessage *autocreator) { 201*1b3f573fSAndroid Build Coastguard Worker id result; 202*1b3f573fSAndroid Build Coastguard Worker GPBDataType fieldDataType = GPBGetFieldDataType(field); 203*1b3f573fSAndroid Build Coastguard Worker switch (fieldDataType) { 204*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeBool: 205*1b3f573fSAndroid Build Coastguard Worker result = [[GPBBoolArray alloc] init]; 206*1b3f573fSAndroid Build Coastguard Worker break; 207*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeFixed32: 208*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeUInt32: 209*1b3f573fSAndroid Build Coastguard Worker result = [[GPBUInt32Array alloc] init]; 210*1b3f573fSAndroid Build Coastguard Worker break; 211*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeInt32: 212*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeSFixed32: 213*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeSInt32: 214*1b3f573fSAndroid Build Coastguard Worker result = [[GPBInt32Array alloc] init]; 215*1b3f573fSAndroid Build Coastguard Worker break; 216*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeFixed64: 217*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeUInt64: 218*1b3f573fSAndroid Build Coastguard Worker result = [[GPBUInt64Array alloc] init]; 219*1b3f573fSAndroid Build Coastguard Worker break; 220*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeInt64: 221*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeSFixed64: 222*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeSInt64: 223*1b3f573fSAndroid Build Coastguard Worker result = [[GPBInt64Array alloc] init]; 224*1b3f573fSAndroid Build Coastguard Worker break; 225*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeFloat: 226*1b3f573fSAndroid Build Coastguard Worker result = [[GPBFloatArray alloc] init]; 227*1b3f573fSAndroid Build Coastguard Worker break; 228*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeDouble: 229*1b3f573fSAndroid Build Coastguard Worker result = [[GPBDoubleArray alloc] init]; 230*1b3f573fSAndroid Build Coastguard Worker break; 231*1b3f573fSAndroid Build Coastguard Worker 232*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeEnum: 233*1b3f573fSAndroid Build Coastguard Worker result = [[GPBEnumArray alloc] 234*1b3f573fSAndroid Build Coastguard Worker initWithValidationFunction:field.enumDescriptor.enumVerifier]; 235*1b3f573fSAndroid Build Coastguard Worker break; 236*1b3f573fSAndroid Build Coastguard Worker 237*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeBytes: 238*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeGroup: 239*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeMessage: 240*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeString: 241*1b3f573fSAndroid Build Coastguard Worker if (autocreator) { 242*1b3f573fSAndroid Build Coastguard Worker result = [[GPBAutocreatedArray alloc] init]; 243*1b3f573fSAndroid Build Coastguard Worker } else { 244*1b3f573fSAndroid Build Coastguard Worker result = [[NSMutableArray alloc] init]; 245*1b3f573fSAndroid Build Coastguard Worker } 246*1b3f573fSAndroid Build Coastguard Worker break; 247*1b3f573fSAndroid Build Coastguard Worker } 248*1b3f573fSAndroid Build Coastguard Worker 249*1b3f573fSAndroid Build Coastguard Worker if (autocreator) { 250*1b3f573fSAndroid Build Coastguard Worker if (GPBDataTypeIsObject(fieldDataType)) { 251*1b3f573fSAndroid Build Coastguard Worker GPBAutocreatedArray *autoArray = result; 252*1b3f573fSAndroid Build Coastguard Worker autoArray->_autocreator = autocreator; 253*1b3f573fSAndroid Build Coastguard Worker } else { 254*1b3f573fSAndroid Build Coastguard Worker GPBInt32Array *gpbArray = result; 255*1b3f573fSAndroid Build Coastguard Worker gpbArray->_autocreator = autocreator; 256*1b3f573fSAndroid Build Coastguard Worker } 257*1b3f573fSAndroid Build Coastguard Worker } 258*1b3f573fSAndroid Build Coastguard Worker 259*1b3f573fSAndroid Build Coastguard Worker return result; 260*1b3f573fSAndroid Build Coastguard Worker} 261*1b3f573fSAndroid Build Coastguard Worker 262*1b3f573fSAndroid Build Coastguard Workerstatic id CreateMapForField(GPBFieldDescriptor *field, 263*1b3f573fSAndroid Build Coastguard Worker GPBMessage *autocreator) { 264*1b3f573fSAndroid Build Coastguard Worker id result; 265*1b3f573fSAndroid Build Coastguard Worker GPBDataType keyDataType = field.mapKeyDataType; 266*1b3f573fSAndroid Build Coastguard Worker GPBDataType valueDataType = GPBGetFieldDataType(field); 267*1b3f573fSAndroid Build Coastguard Worker switch (keyDataType) { 268*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeBool: 269*1b3f573fSAndroid Build Coastguard Worker switch (valueDataType) { 270*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeBool: 271*1b3f573fSAndroid Build Coastguard Worker result = [[GPBBoolBoolDictionary alloc] init]; 272*1b3f573fSAndroid Build Coastguard Worker break; 273*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeFixed32: 274*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeUInt32: 275*1b3f573fSAndroid Build Coastguard Worker result = [[GPBBoolUInt32Dictionary alloc] init]; 276*1b3f573fSAndroid Build Coastguard Worker break; 277*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeInt32: 278*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeSFixed32: 279*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeSInt32: 280*1b3f573fSAndroid Build Coastguard Worker result = [[GPBBoolInt32Dictionary alloc] init]; 281*1b3f573fSAndroid Build Coastguard Worker break; 282*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeFixed64: 283*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeUInt64: 284*1b3f573fSAndroid Build Coastguard Worker result = [[GPBBoolUInt64Dictionary alloc] init]; 285*1b3f573fSAndroid Build Coastguard Worker break; 286*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeInt64: 287*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeSFixed64: 288*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeSInt64: 289*1b3f573fSAndroid Build Coastguard Worker result = [[GPBBoolInt64Dictionary alloc] init]; 290*1b3f573fSAndroid Build Coastguard Worker break; 291*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeFloat: 292*1b3f573fSAndroid Build Coastguard Worker result = [[GPBBoolFloatDictionary alloc] init]; 293*1b3f573fSAndroid Build Coastguard Worker break; 294*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeDouble: 295*1b3f573fSAndroid Build Coastguard Worker result = [[GPBBoolDoubleDictionary alloc] init]; 296*1b3f573fSAndroid Build Coastguard Worker break; 297*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeEnum: 298*1b3f573fSAndroid Build Coastguard Worker result = [[GPBBoolEnumDictionary alloc] 299*1b3f573fSAndroid Build Coastguard Worker initWithValidationFunction:field.enumDescriptor.enumVerifier]; 300*1b3f573fSAndroid Build Coastguard Worker break; 301*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeBytes: 302*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeMessage: 303*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeString: 304*1b3f573fSAndroid Build Coastguard Worker result = [[GPBBoolObjectDictionary alloc] init]; 305*1b3f573fSAndroid Build Coastguard Worker break; 306*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeGroup: 307*1b3f573fSAndroid Build Coastguard Worker NSCAssert(NO, @"shouldn't happen"); 308*1b3f573fSAndroid Build Coastguard Worker return nil; 309*1b3f573fSAndroid Build Coastguard Worker } 310*1b3f573fSAndroid Build Coastguard Worker break; 311*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeFixed32: 312*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeUInt32: 313*1b3f573fSAndroid Build Coastguard Worker switch (valueDataType) { 314*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeBool: 315*1b3f573fSAndroid Build Coastguard Worker result = [[GPBUInt32BoolDictionary alloc] init]; 316*1b3f573fSAndroid Build Coastguard Worker break; 317*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeFixed32: 318*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeUInt32: 319*1b3f573fSAndroid Build Coastguard Worker result = [[GPBUInt32UInt32Dictionary alloc] init]; 320*1b3f573fSAndroid Build Coastguard Worker break; 321*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeInt32: 322*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeSFixed32: 323*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeSInt32: 324*1b3f573fSAndroid Build Coastguard Worker result = [[GPBUInt32Int32Dictionary alloc] init]; 325*1b3f573fSAndroid Build Coastguard Worker break; 326*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeFixed64: 327*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeUInt64: 328*1b3f573fSAndroid Build Coastguard Worker result = [[GPBUInt32UInt64Dictionary alloc] init]; 329*1b3f573fSAndroid Build Coastguard Worker break; 330*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeInt64: 331*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeSFixed64: 332*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeSInt64: 333*1b3f573fSAndroid Build Coastguard Worker result = [[GPBUInt32Int64Dictionary alloc] init]; 334*1b3f573fSAndroid Build Coastguard Worker break; 335*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeFloat: 336*1b3f573fSAndroid Build Coastguard Worker result = [[GPBUInt32FloatDictionary alloc] init]; 337*1b3f573fSAndroid Build Coastguard Worker break; 338*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeDouble: 339*1b3f573fSAndroid Build Coastguard Worker result = [[GPBUInt32DoubleDictionary alloc] init]; 340*1b3f573fSAndroid Build Coastguard Worker break; 341*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeEnum: 342*1b3f573fSAndroid Build Coastguard Worker result = [[GPBUInt32EnumDictionary alloc] 343*1b3f573fSAndroid Build Coastguard Worker initWithValidationFunction:field.enumDescriptor.enumVerifier]; 344*1b3f573fSAndroid Build Coastguard Worker break; 345*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeBytes: 346*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeMessage: 347*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeString: 348*1b3f573fSAndroid Build Coastguard Worker result = [[GPBUInt32ObjectDictionary alloc] init]; 349*1b3f573fSAndroid Build Coastguard Worker break; 350*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeGroup: 351*1b3f573fSAndroid Build Coastguard Worker NSCAssert(NO, @"shouldn't happen"); 352*1b3f573fSAndroid Build Coastguard Worker return nil; 353*1b3f573fSAndroid Build Coastguard Worker } 354*1b3f573fSAndroid Build Coastguard Worker break; 355*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeInt32: 356*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeSFixed32: 357*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeSInt32: 358*1b3f573fSAndroid Build Coastguard Worker switch (valueDataType) { 359*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeBool: 360*1b3f573fSAndroid Build Coastguard Worker result = [[GPBInt32BoolDictionary alloc] init]; 361*1b3f573fSAndroid Build Coastguard Worker break; 362*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeFixed32: 363*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeUInt32: 364*1b3f573fSAndroid Build Coastguard Worker result = [[GPBInt32UInt32Dictionary alloc] init]; 365*1b3f573fSAndroid Build Coastguard Worker break; 366*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeInt32: 367*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeSFixed32: 368*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeSInt32: 369*1b3f573fSAndroid Build Coastguard Worker result = [[GPBInt32Int32Dictionary alloc] init]; 370*1b3f573fSAndroid Build Coastguard Worker break; 371*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeFixed64: 372*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeUInt64: 373*1b3f573fSAndroid Build Coastguard Worker result = [[GPBInt32UInt64Dictionary alloc] init]; 374*1b3f573fSAndroid Build Coastguard Worker break; 375*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeInt64: 376*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeSFixed64: 377*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeSInt64: 378*1b3f573fSAndroid Build Coastguard Worker result = [[GPBInt32Int64Dictionary alloc] init]; 379*1b3f573fSAndroid Build Coastguard Worker break; 380*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeFloat: 381*1b3f573fSAndroid Build Coastguard Worker result = [[GPBInt32FloatDictionary alloc] init]; 382*1b3f573fSAndroid Build Coastguard Worker break; 383*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeDouble: 384*1b3f573fSAndroid Build Coastguard Worker result = [[GPBInt32DoubleDictionary alloc] init]; 385*1b3f573fSAndroid Build Coastguard Worker break; 386*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeEnum: 387*1b3f573fSAndroid Build Coastguard Worker result = [[GPBInt32EnumDictionary alloc] 388*1b3f573fSAndroid Build Coastguard Worker initWithValidationFunction:field.enumDescriptor.enumVerifier]; 389*1b3f573fSAndroid Build Coastguard Worker break; 390*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeBytes: 391*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeMessage: 392*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeString: 393*1b3f573fSAndroid Build Coastguard Worker result = [[GPBInt32ObjectDictionary alloc] init]; 394*1b3f573fSAndroid Build Coastguard Worker break; 395*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeGroup: 396*1b3f573fSAndroid Build Coastguard Worker NSCAssert(NO, @"shouldn't happen"); 397*1b3f573fSAndroid Build Coastguard Worker return nil; 398*1b3f573fSAndroid Build Coastguard Worker } 399*1b3f573fSAndroid Build Coastguard Worker break; 400*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeFixed64: 401*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeUInt64: 402*1b3f573fSAndroid Build Coastguard Worker switch (valueDataType) { 403*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeBool: 404*1b3f573fSAndroid Build Coastguard Worker result = [[GPBUInt64BoolDictionary alloc] init]; 405*1b3f573fSAndroid Build Coastguard Worker break; 406*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeFixed32: 407*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeUInt32: 408*1b3f573fSAndroid Build Coastguard Worker result = [[GPBUInt64UInt32Dictionary alloc] init]; 409*1b3f573fSAndroid Build Coastguard Worker break; 410*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeInt32: 411*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeSFixed32: 412*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeSInt32: 413*1b3f573fSAndroid Build Coastguard Worker result = [[GPBUInt64Int32Dictionary alloc] init]; 414*1b3f573fSAndroid Build Coastguard Worker break; 415*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeFixed64: 416*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeUInt64: 417*1b3f573fSAndroid Build Coastguard Worker result = [[GPBUInt64UInt64Dictionary alloc] init]; 418*1b3f573fSAndroid Build Coastguard Worker break; 419*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeInt64: 420*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeSFixed64: 421*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeSInt64: 422*1b3f573fSAndroid Build Coastguard Worker result = [[GPBUInt64Int64Dictionary alloc] init]; 423*1b3f573fSAndroid Build Coastguard Worker break; 424*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeFloat: 425*1b3f573fSAndroid Build Coastguard Worker result = [[GPBUInt64FloatDictionary alloc] init]; 426*1b3f573fSAndroid Build Coastguard Worker break; 427*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeDouble: 428*1b3f573fSAndroid Build Coastguard Worker result = [[GPBUInt64DoubleDictionary alloc] init]; 429*1b3f573fSAndroid Build Coastguard Worker break; 430*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeEnum: 431*1b3f573fSAndroid Build Coastguard Worker result = [[GPBUInt64EnumDictionary alloc] 432*1b3f573fSAndroid Build Coastguard Worker initWithValidationFunction:field.enumDescriptor.enumVerifier]; 433*1b3f573fSAndroid Build Coastguard Worker break; 434*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeBytes: 435*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeMessage: 436*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeString: 437*1b3f573fSAndroid Build Coastguard Worker result = [[GPBUInt64ObjectDictionary alloc] init]; 438*1b3f573fSAndroid Build Coastguard Worker break; 439*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeGroup: 440*1b3f573fSAndroid Build Coastguard Worker NSCAssert(NO, @"shouldn't happen"); 441*1b3f573fSAndroid Build Coastguard Worker return nil; 442*1b3f573fSAndroid Build Coastguard Worker } 443*1b3f573fSAndroid Build Coastguard Worker break; 444*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeInt64: 445*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeSFixed64: 446*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeSInt64: 447*1b3f573fSAndroid Build Coastguard Worker switch (valueDataType) { 448*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeBool: 449*1b3f573fSAndroid Build Coastguard Worker result = [[GPBInt64BoolDictionary alloc] init]; 450*1b3f573fSAndroid Build Coastguard Worker break; 451*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeFixed32: 452*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeUInt32: 453*1b3f573fSAndroid Build Coastguard Worker result = [[GPBInt64UInt32Dictionary alloc] init]; 454*1b3f573fSAndroid Build Coastguard Worker break; 455*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeInt32: 456*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeSFixed32: 457*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeSInt32: 458*1b3f573fSAndroid Build Coastguard Worker result = [[GPBInt64Int32Dictionary alloc] init]; 459*1b3f573fSAndroid Build Coastguard Worker break; 460*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeFixed64: 461*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeUInt64: 462*1b3f573fSAndroid Build Coastguard Worker result = [[GPBInt64UInt64Dictionary alloc] init]; 463*1b3f573fSAndroid Build Coastguard Worker break; 464*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeInt64: 465*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeSFixed64: 466*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeSInt64: 467*1b3f573fSAndroid Build Coastguard Worker result = [[GPBInt64Int64Dictionary alloc] init]; 468*1b3f573fSAndroid Build Coastguard Worker break; 469*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeFloat: 470*1b3f573fSAndroid Build Coastguard Worker result = [[GPBInt64FloatDictionary alloc] init]; 471*1b3f573fSAndroid Build Coastguard Worker break; 472*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeDouble: 473*1b3f573fSAndroid Build Coastguard Worker result = [[GPBInt64DoubleDictionary alloc] init]; 474*1b3f573fSAndroid Build Coastguard Worker break; 475*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeEnum: 476*1b3f573fSAndroid Build Coastguard Worker result = [[GPBInt64EnumDictionary alloc] 477*1b3f573fSAndroid Build Coastguard Worker initWithValidationFunction:field.enumDescriptor.enumVerifier]; 478*1b3f573fSAndroid Build Coastguard Worker break; 479*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeBytes: 480*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeMessage: 481*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeString: 482*1b3f573fSAndroid Build Coastguard Worker result = [[GPBInt64ObjectDictionary alloc] init]; 483*1b3f573fSAndroid Build Coastguard Worker break; 484*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeGroup: 485*1b3f573fSAndroid Build Coastguard Worker NSCAssert(NO, @"shouldn't happen"); 486*1b3f573fSAndroid Build Coastguard Worker return nil; 487*1b3f573fSAndroid Build Coastguard Worker } 488*1b3f573fSAndroid Build Coastguard Worker break; 489*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeString: 490*1b3f573fSAndroid Build Coastguard Worker switch (valueDataType) { 491*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeBool: 492*1b3f573fSAndroid Build Coastguard Worker result = [[GPBStringBoolDictionary alloc] init]; 493*1b3f573fSAndroid Build Coastguard Worker break; 494*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeFixed32: 495*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeUInt32: 496*1b3f573fSAndroid Build Coastguard Worker result = [[GPBStringUInt32Dictionary alloc] init]; 497*1b3f573fSAndroid Build Coastguard Worker break; 498*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeInt32: 499*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeSFixed32: 500*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeSInt32: 501*1b3f573fSAndroid Build Coastguard Worker result = [[GPBStringInt32Dictionary alloc] init]; 502*1b3f573fSAndroid Build Coastguard Worker break; 503*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeFixed64: 504*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeUInt64: 505*1b3f573fSAndroid Build Coastguard Worker result = [[GPBStringUInt64Dictionary alloc] init]; 506*1b3f573fSAndroid Build Coastguard Worker break; 507*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeInt64: 508*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeSFixed64: 509*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeSInt64: 510*1b3f573fSAndroid Build Coastguard Worker result = [[GPBStringInt64Dictionary alloc] init]; 511*1b3f573fSAndroid Build Coastguard Worker break; 512*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeFloat: 513*1b3f573fSAndroid Build Coastguard Worker result = [[GPBStringFloatDictionary alloc] init]; 514*1b3f573fSAndroid Build Coastguard Worker break; 515*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeDouble: 516*1b3f573fSAndroid Build Coastguard Worker result = [[GPBStringDoubleDictionary alloc] init]; 517*1b3f573fSAndroid Build Coastguard Worker break; 518*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeEnum: 519*1b3f573fSAndroid Build Coastguard Worker result = [[GPBStringEnumDictionary alloc] 520*1b3f573fSAndroid Build Coastguard Worker initWithValidationFunction:field.enumDescriptor.enumVerifier]; 521*1b3f573fSAndroid Build Coastguard Worker break; 522*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeBytes: 523*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeMessage: 524*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeString: 525*1b3f573fSAndroid Build Coastguard Worker if (autocreator) { 526*1b3f573fSAndroid Build Coastguard Worker result = [[GPBAutocreatedDictionary alloc] init]; 527*1b3f573fSAndroid Build Coastguard Worker } else { 528*1b3f573fSAndroid Build Coastguard Worker result = [[NSMutableDictionary alloc] init]; 529*1b3f573fSAndroid Build Coastguard Worker } 530*1b3f573fSAndroid Build Coastguard Worker break; 531*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeGroup: 532*1b3f573fSAndroid Build Coastguard Worker NSCAssert(NO, @"shouldn't happen"); 533*1b3f573fSAndroid Build Coastguard Worker return nil; 534*1b3f573fSAndroid Build Coastguard Worker } 535*1b3f573fSAndroid Build Coastguard Worker break; 536*1b3f573fSAndroid Build Coastguard Worker 537*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeFloat: 538*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeDouble: 539*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeEnum: 540*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeBytes: 541*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeGroup: 542*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeMessage: 543*1b3f573fSAndroid Build Coastguard Worker NSCAssert(NO, @"shouldn't happen"); 544*1b3f573fSAndroid Build Coastguard Worker return nil; 545*1b3f573fSAndroid Build Coastguard Worker } 546*1b3f573fSAndroid Build Coastguard Worker 547*1b3f573fSAndroid Build Coastguard Worker if (autocreator) { 548*1b3f573fSAndroid Build Coastguard Worker if ((keyDataType == GPBDataTypeString) && 549*1b3f573fSAndroid Build Coastguard Worker GPBDataTypeIsObject(valueDataType)) { 550*1b3f573fSAndroid Build Coastguard Worker GPBAutocreatedDictionary *autoDict = result; 551*1b3f573fSAndroid Build Coastguard Worker autoDict->_autocreator = autocreator; 552*1b3f573fSAndroid Build Coastguard Worker } else { 553*1b3f573fSAndroid Build Coastguard Worker GPBInt32Int32Dictionary *gpbDict = result; 554*1b3f573fSAndroid Build Coastguard Worker gpbDict->_autocreator = autocreator; 555*1b3f573fSAndroid Build Coastguard Worker } 556*1b3f573fSAndroid Build Coastguard Worker } 557*1b3f573fSAndroid Build Coastguard Worker 558*1b3f573fSAndroid Build Coastguard Worker return result; 559*1b3f573fSAndroid Build Coastguard Worker} 560*1b3f573fSAndroid Build Coastguard Worker 561*1b3f573fSAndroid Build Coastguard Worker#if !defined(__clang_analyzer__) 562*1b3f573fSAndroid Build Coastguard Worker// These functions are blocked from the analyzer because the analyzer sees the 563*1b3f573fSAndroid Build Coastguard Worker// GPBSetRetainedObjectIvarWithFieldPrivate() call as consuming the array/map, 564*1b3f573fSAndroid Build Coastguard Worker// so use of the array/map after the call returns is flagged as a use after 565*1b3f573fSAndroid Build Coastguard Worker// free. 566*1b3f573fSAndroid Build Coastguard Worker// But GPBSetRetainedObjectIvarWithFieldPrivate() is "consuming" the retain 567*1b3f573fSAndroid Build Coastguard Worker// count be holding onto the object (it is transferring it), the object is 568*1b3f573fSAndroid Build Coastguard Worker// still valid after returning from the call. The other way to avoid this 569*1b3f573fSAndroid Build Coastguard Worker// would be to add a -retain/-autorelease, but that would force every 570*1b3f573fSAndroid Build Coastguard Worker// repeated/map field parsed into the autorelease pool which is both a memory 571*1b3f573fSAndroid Build Coastguard Worker// and performance hit. 572*1b3f573fSAndroid Build Coastguard Worker 573*1b3f573fSAndroid Build Coastguard Workerstatic id GetOrCreateArrayIvarWithField(GPBMessage *self, 574*1b3f573fSAndroid Build Coastguard Worker GPBFieldDescriptor *field) { 575*1b3f573fSAndroid Build Coastguard Worker id array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); 576*1b3f573fSAndroid Build Coastguard Worker if (!array) { 577*1b3f573fSAndroid Build Coastguard Worker // No lock needed, this is called from places expecting to mutate 578*1b3f573fSAndroid Build Coastguard Worker // so no threading protection is needed. 579*1b3f573fSAndroid Build Coastguard Worker array = CreateArrayForField(field, nil); 580*1b3f573fSAndroid Build Coastguard Worker GPBSetRetainedObjectIvarWithFieldPrivate(self, field, array); 581*1b3f573fSAndroid Build Coastguard Worker } 582*1b3f573fSAndroid Build Coastguard Worker return array; 583*1b3f573fSAndroid Build Coastguard Worker} 584*1b3f573fSAndroid Build Coastguard Worker 585*1b3f573fSAndroid Build Coastguard Worker// This is like GPBGetObjectIvarWithField(), but for arrays, it should 586*1b3f573fSAndroid Build Coastguard Worker// only be used to wire the method into the class. 587*1b3f573fSAndroid Build Coastguard Workerstatic id GetArrayIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) { 588*1b3f573fSAndroid Build Coastguard Worker uint8_t *storage = (uint8_t *)self->messageStorage_; 589*1b3f573fSAndroid Build Coastguard Worker _Atomic(id) *typePtr = (_Atomic(id) *)&storage[field->description_->offset]; 590*1b3f573fSAndroid Build Coastguard Worker id array = atomic_load(typePtr); 591*1b3f573fSAndroid Build Coastguard Worker if (array) { 592*1b3f573fSAndroid Build Coastguard Worker return array; 593*1b3f573fSAndroid Build Coastguard Worker } 594*1b3f573fSAndroid Build Coastguard Worker 595*1b3f573fSAndroid Build Coastguard Worker id expected = nil; 596*1b3f573fSAndroid Build Coastguard Worker id autocreated = CreateArrayForField(field, self); 597*1b3f573fSAndroid Build Coastguard Worker if (atomic_compare_exchange_strong(typePtr, &expected, autocreated)) { 598*1b3f573fSAndroid Build Coastguard Worker // Value was set, return it. 599*1b3f573fSAndroid Build Coastguard Worker return autocreated; 600*1b3f573fSAndroid Build Coastguard Worker } 601*1b3f573fSAndroid Build Coastguard Worker 602*1b3f573fSAndroid Build Coastguard Worker // Some other thread set it, release the one created and return what got set. 603*1b3f573fSAndroid Build Coastguard Worker if (GPBFieldDataTypeIsObject(field)) { 604*1b3f573fSAndroid Build Coastguard Worker GPBAutocreatedArray *autoArray = autocreated; 605*1b3f573fSAndroid Build Coastguard Worker autoArray->_autocreator = nil; 606*1b3f573fSAndroid Build Coastguard Worker } else { 607*1b3f573fSAndroid Build Coastguard Worker GPBInt32Array *gpbArray = autocreated; 608*1b3f573fSAndroid Build Coastguard Worker gpbArray->_autocreator = nil; 609*1b3f573fSAndroid Build Coastguard Worker } 610*1b3f573fSAndroid Build Coastguard Worker [autocreated release]; 611*1b3f573fSAndroid Build Coastguard Worker return expected; 612*1b3f573fSAndroid Build Coastguard Worker} 613*1b3f573fSAndroid Build Coastguard Worker 614*1b3f573fSAndroid Build Coastguard Workerstatic id GetOrCreateMapIvarWithField(GPBMessage *self, 615*1b3f573fSAndroid Build Coastguard Worker GPBFieldDescriptor *field) { 616*1b3f573fSAndroid Build Coastguard Worker id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); 617*1b3f573fSAndroid Build Coastguard Worker if (!dict) { 618*1b3f573fSAndroid Build Coastguard Worker // No lock needed, this is called from places expecting to mutate 619*1b3f573fSAndroid Build Coastguard Worker // so no threading protection is needed. 620*1b3f573fSAndroid Build Coastguard Worker dict = CreateMapForField(field, nil); 621*1b3f573fSAndroid Build Coastguard Worker GPBSetRetainedObjectIvarWithFieldPrivate(self, field, dict); 622*1b3f573fSAndroid Build Coastguard Worker } 623*1b3f573fSAndroid Build Coastguard Worker return dict; 624*1b3f573fSAndroid Build Coastguard Worker} 625*1b3f573fSAndroid Build Coastguard Worker 626*1b3f573fSAndroid Build Coastguard Worker// This is like GPBGetObjectIvarWithField(), but for maps, it should 627*1b3f573fSAndroid Build Coastguard Worker// only be used to wire the method into the class. 628*1b3f573fSAndroid Build Coastguard Workerstatic id GetMapIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) { 629*1b3f573fSAndroid Build Coastguard Worker uint8_t *storage = (uint8_t *)self->messageStorage_; 630*1b3f573fSAndroid Build Coastguard Worker _Atomic(id) *typePtr = (_Atomic(id) *)&storage[field->description_->offset]; 631*1b3f573fSAndroid Build Coastguard Worker id dict = atomic_load(typePtr); 632*1b3f573fSAndroid Build Coastguard Worker if (dict) { 633*1b3f573fSAndroid Build Coastguard Worker return dict; 634*1b3f573fSAndroid Build Coastguard Worker } 635*1b3f573fSAndroid Build Coastguard Worker 636*1b3f573fSAndroid Build Coastguard Worker id expected = nil; 637*1b3f573fSAndroid Build Coastguard Worker id autocreated = CreateMapForField(field, self); 638*1b3f573fSAndroid Build Coastguard Worker if (atomic_compare_exchange_strong(typePtr, &expected, autocreated)) { 639*1b3f573fSAndroid Build Coastguard Worker // Value was set, return it. 640*1b3f573fSAndroid Build Coastguard Worker return autocreated; 641*1b3f573fSAndroid Build Coastguard Worker } 642*1b3f573fSAndroid Build Coastguard Worker 643*1b3f573fSAndroid Build Coastguard Worker // Some other thread set it, release the one created and return what got set. 644*1b3f573fSAndroid Build Coastguard Worker if ((field.mapKeyDataType == GPBDataTypeString) && 645*1b3f573fSAndroid Build Coastguard Worker GPBFieldDataTypeIsObject(field)) { 646*1b3f573fSAndroid Build Coastguard Worker GPBAutocreatedDictionary *autoDict = autocreated; 647*1b3f573fSAndroid Build Coastguard Worker autoDict->_autocreator = nil; 648*1b3f573fSAndroid Build Coastguard Worker } else { 649*1b3f573fSAndroid Build Coastguard Worker GPBInt32Int32Dictionary *gpbDict = autocreated; 650*1b3f573fSAndroid Build Coastguard Worker gpbDict->_autocreator = nil; 651*1b3f573fSAndroid Build Coastguard Worker } 652*1b3f573fSAndroid Build Coastguard Worker [autocreated release]; 653*1b3f573fSAndroid Build Coastguard Worker return expected; 654*1b3f573fSAndroid Build Coastguard Worker} 655*1b3f573fSAndroid Build Coastguard Worker 656*1b3f573fSAndroid Build Coastguard Worker#endif // !defined(__clang_analyzer__) 657*1b3f573fSAndroid Build Coastguard Worker 658*1b3f573fSAndroid Build Coastguard WorkerGPBMessage *GPBCreateMessageWithAutocreator(Class msgClass, 659*1b3f573fSAndroid Build Coastguard Worker GPBMessage *autocreator, 660*1b3f573fSAndroid Build Coastguard Worker GPBFieldDescriptor *field) { 661*1b3f573fSAndroid Build Coastguard Worker GPBMessage *message = [[msgClass alloc] init]; 662*1b3f573fSAndroid Build Coastguard Worker message->autocreator_ = autocreator; 663*1b3f573fSAndroid Build Coastguard Worker message->autocreatorField_ = [field retain]; 664*1b3f573fSAndroid Build Coastguard Worker return message; 665*1b3f573fSAndroid Build Coastguard Worker} 666*1b3f573fSAndroid Build Coastguard Worker 667*1b3f573fSAndroid Build Coastguard Workerstatic GPBMessage *CreateMessageWithAutocreatorForExtension( 668*1b3f573fSAndroid Build Coastguard Worker Class msgClass, GPBMessage *autocreator, GPBExtensionDescriptor *extension) 669*1b3f573fSAndroid Build Coastguard Worker __attribute__((ns_returns_retained)); 670*1b3f573fSAndroid Build Coastguard Worker 671*1b3f573fSAndroid Build Coastguard Workerstatic GPBMessage *CreateMessageWithAutocreatorForExtension( 672*1b3f573fSAndroid Build Coastguard Worker Class msgClass, GPBMessage *autocreator, 673*1b3f573fSAndroid Build Coastguard Worker GPBExtensionDescriptor *extension) { 674*1b3f573fSAndroid Build Coastguard Worker GPBMessage *message = [[msgClass alloc] init]; 675*1b3f573fSAndroid Build Coastguard Worker message->autocreator_ = autocreator; 676*1b3f573fSAndroid Build Coastguard Worker message->autocreatorExtension_ = [extension retain]; 677*1b3f573fSAndroid Build Coastguard Worker return message; 678*1b3f573fSAndroid Build Coastguard Worker} 679*1b3f573fSAndroid Build Coastguard Worker 680*1b3f573fSAndroid Build Coastguard WorkerBOOL GPBWasMessageAutocreatedBy(GPBMessage *message, GPBMessage *parent) { 681*1b3f573fSAndroid Build Coastguard Worker return (message->autocreator_ == parent); 682*1b3f573fSAndroid Build Coastguard Worker} 683*1b3f573fSAndroid Build Coastguard Worker 684*1b3f573fSAndroid Build Coastguard Workervoid GPBBecomeVisibleToAutocreator(GPBMessage *self) { 685*1b3f573fSAndroid Build Coastguard Worker // Message objects that are implicitly created by accessing a message field 686*1b3f573fSAndroid Build Coastguard Worker // are initially not visible via the hasX selector. This method makes them 687*1b3f573fSAndroid Build Coastguard Worker // visible. 688*1b3f573fSAndroid Build Coastguard Worker if (self->autocreator_) { 689*1b3f573fSAndroid Build Coastguard Worker // This will recursively make all parent messages visible until it reaches a 690*1b3f573fSAndroid Build Coastguard Worker // super-creator that's visible. 691*1b3f573fSAndroid Build Coastguard Worker if (self->autocreatorField_) { 692*1b3f573fSAndroid Build Coastguard Worker GPBSetObjectIvarWithFieldPrivate(self->autocreator_, 693*1b3f573fSAndroid Build Coastguard Worker self->autocreatorField_, self); 694*1b3f573fSAndroid Build Coastguard Worker } else { 695*1b3f573fSAndroid Build Coastguard Worker [self->autocreator_ setExtension:self->autocreatorExtension_ value:self]; 696*1b3f573fSAndroid Build Coastguard Worker } 697*1b3f573fSAndroid Build Coastguard Worker } 698*1b3f573fSAndroid Build Coastguard Worker} 699*1b3f573fSAndroid Build Coastguard Worker 700*1b3f573fSAndroid Build Coastguard Workervoid GPBAutocreatedArrayModified(GPBMessage *self, id array) { 701*1b3f573fSAndroid Build Coastguard Worker // When one of our autocreated arrays adds elements, make it visible. 702*1b3f573fSAndroid Build Coastguard Worker GPBDescriptor *descriptor = [[self class] descriptor]; 703*1b3f573fSAndroid Build Coastguard Worker for (GPBFieldDescriptor *field in descriptor->fields_) { 704*1b3f573fSAndroid Build Coastguard Worker if (field.fieldType == GPBFieldTypeRepeated) { 705*1b3f573fSAndroid Build Coastguard Worker id curArray = GPBGetObjectIvarWithFieldNoAutocreate(self, field); 706*1b3f573fSAndroid Build Coastguard Worker if (curArray == array) { 707*1b3f573fSAndroid Build Coastguard Worker if (GPBFieldDataTypeIsObject(field)) { 708*1b3f573fSAndroid Build Coastguard Worker GPBAutocreatedArray *autoArray = array; 709*1b3f573fSAndroid Build Coastguard Worker autoArray->_autocreator = nil; 710*1b3f573fSAndroid Build Coastguard Worker } else { 711*1b3f573fSAndroid Build Coastguard Worker GPBInt32Array *gpbArray = array; 712*1b3f573fSAndroid Build Coastguard Worker gpbArray->_autocreator = nil; 713*1b3f573fSAndroid Build Coastguard Worker } 714*1b3f573fSAndroid Build Coastguard Worker GPBBecomeVisibleToAutocreator(self); 715*1b3f573fSAndroid Build Coastguard Worker return; 716*1b3f573fSAndroid Build Coastguard Worker } 717*1b3f573fSAndroid Build Coastguard Worker } 718*1b3f573fSAndroid Build Coastguard Worker } 719*1b3f573fSAndroid Build Coastguard Worker NSCAssert(NO, @"Unknown autocreated %@ for %@.", [array class], self); 720*1b3f573fSAndroid Build Coastguard Worker} 721*1b3f573fSAndroid Build Coastguard Worker 722*1b3f573fSAndroid Build Coastguard Workervoid GPBAutocreatedDictionaryModified(GPBMessage *self, id dictionary) { 723*1b3f573fSAndroid Build Coastguard Worker // When one of our autocreated dicts adds elements, make it visible. 724*1b3f573fSAndroid Build Coastguard Worker GPBDescriptor *descriptor = [[self class] descriptor]; 725*1b3f573fSAndroid Build Coastguard Worker for (GPBFieldDescriptor *field in descriptor->fields_) { 726*1b3f573fSAndroid Build Coastguard Worker if (field.fieldType == GPBFieldTypeMap) { 727*1b3f573fSAndroid Build Coastguard Worker id curDict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); 728*1b3f573fSAndroid Build Coastguard Worker if (curDict == dictionary) { 729*1b3f573fSAndroid Build Coastguard Worker if ((field.mapKeyDataType == GPBDataTypeString) && 730*1b3f573fSAndroid Build Coastguard Worker GPBFieldDataTypeIsObject(field)) { 731*1b3f573fSAndroid Build Coastguard Worker GPBAutocreatedDictionary *autoDict = dictionary; 732*1b3f573fSAndroid Build Coastguard Worker autoDict->_autocreator = nil; 733*1b3f573fSAndroid Build Coastguard Worker } else { 734*1b3f573fSAndroid Build Coastguard Worker GPBInt32Int32Dictionary *gpbDict = dictionary; 735*1b3f573fSAndroid Build Coastguard Worker gpbDict->_autocreator = nil; 736*1b3f573fSAndroid Build Coastguard Worker } 737*1b3f573fSAndroid Build Coastguard Worker GPBBecomeVisibleToAutocreator(self); 738*1b3f573fSAndroid Build Coastguard Worker return; 739*1b3f573fSAndroid Build Coastguard Worker } 740*1b3f573fSAndroid Build Coastguard Worker } 741*1b3f573fSAndroid Build Coastguard Worker } 742*1b3f573fSAndroid Build Coastguard Worker NSCAssert(NO, @"Unknown autocreated %@ for %@.", [dictionary class], self); 743*1b3f573fSAndroid Build Coastguard Worker} 744*1b3f573fSAndroid Build Coastguard Worker 745*1b3f573fSAndroid Build Coastguard Workervoid GPBClearMessageAutocreator(GPBMessage *self) { 746*1b3f573fSAndroid Build Coastguard Worker if ((self == nil) || !self->autocreator_) { 747*1b3f573fSAndroid Build Coastguard Worker return; 748*1b3f573fSAndroid Build Coastguard Worker } 749*1b3f573fSAndroid Build Coastguard Worker 750*1b3f573fSAndroid Build Coastguard Worker#if defined(DEBUG) && DEBUG && !defined(NS_BLOCK_ASSERTIONS) 751*1b3f573fSAndroid Build Coastguard Worker // Either the autocreator must have its "has" flag set to YES, or it must be 752*1b3f573fSAndroid Build Coastguard Worker // NO and not equal to ourselves. 753*1b3f573fSAndroid Build Coastguard Worker BOOL autocreatorHas = 754*1b3f573fSAndroid Build Coastguard Worker (self->autocreatorField_ 755*1b3f573fSAndroid Build Coastguard Worker ? GPBGetHasIvarField(self->autocreator_, self->autocreatorField_) 756*1b3f573fSAndroid Build Coastguard Worker : [self->autocreator_ hasExtension:self->autocreatorExtension_]); 757*1b3f573fSAndroid Build Coastguard Worker GPBMessage *autocreatorFieldValue = 758*1b3f573fSAndroid Build Coastguard Worker (self->autocreatorField_ 759*1b3f573fSAndroid Build Coastguard Worker ? GPBGetObjectIvarWithFieldNoAutocreate(self->autocreator_, 760*1b3f573fSAndroid Build Coastguard Worker self->autocreatorField_) 761*1b3f573fSAndroid Build Coastguard Worker : [self->autocreator_->autocreatedExtensionMap_ 762*1b3f573fSAndroid Build Coastguard Worker objectForKey:self->autocreatorExtension_]); 763*1b3f573fSAndroid Build Coastguard Worker NSCAssert(autocreatorHas || autocreatorFieldValue != self, 764*1b3f573fSAndroid Build Coastguard Worker @"Cannot clear autocreator because it still refers to self, self: %@.", 765*1b3f573fSAndroid Build Coastguard Worker self); 766*1b3f573fSAndroid Build Coastguard Worker 767*1b3f573fSAndroid Build Coastguard Worker#endif // DEBUG && !defined(NS_BLOCK_ASSERTIONS) 768*1b3f573fSAndroid Build Coastguard Worker 769*1b3f573fSAndroid Build Coastguard Worker self->autocreator_ = nil; 770*1b3f573fSAndroid Build Coastguard Worker [self->autocreatorField_ release]; 771*1b3f573fSAndroid Build Coastguard Worker self->autocreatorField_ = nil; 772*1b3f573fSAndroid Build Coastguard Worker [self->autocreatorExtension_ release]; 773*1b3f573fSAndroid Build Coastguard Worker self->autocreatorExtension_ = nil; 774*1b3f573fSAndroid Build Coastguard Worker} 775*1b3f573fSAndroid Build Coastguard Worker 776*1b3f573fSAndroid Build Coastguard Worker// Call this before using the readOnlySemaphore_. This ensures it is created only once. 777*1b3f573fSAndroid Build Coastguard Workervoid GPBPrepareReadOnlySemaphore(GPBMessage *self) { 778*1b3f573fSAndroid Build Coastguard Worker#pragma clang diagnostic push 779*1b3f573fSAndroid Build Coastguard Worker#pragma clang diagnostic ignored "-Wdirect-ivar-access" 780*1b3f573fSAndroid Build Coastguard Worker 781*1b3f573fSAndroid Build Coastguard Worker // Create the semaphore on demand (rather than init) as developers might not cause them 782*1b3f573fSAndroid Build Coastguard Worker // to be needed, and the heap usage can add up. The atomic swap is used to avoid needing 783*1b3f573fSAndroid Build Coastguard Worker // another lock around creating it. 784*1b3f573fSAndroid Build Coastguard Worker if (self->readOnlySemaphore_ == nil) { 785*1b3f573fSAndroid Build Coastguard Worker dispatch_semaphore_t worker = dispatch_semaphore_create(1); 786*1b3f573fSAndroid Build Coastguard Worker dispatch_semaphore_t expected = nil; 787*1b3f573fSAndroid Build Coastguard Worker if (!atomic_compare_exchange_strong(&self->readOnlySemaphore_, &expected, worker)) { 788*1b3f573fSAndroid Build Coastguard Worker dispatch_release(worker); 789*1b3f573fSAndroid Build Coastguard Worker } 790*1b3f573fSAndroid Build Coastguard Worker#if defined(__clang_analyzer__) 791*1b3f573fSAndroid Build Coastguard Worker // The Xcode 9.2 (and 9.3 beta) static analyzer thinks worker is leaked 792*1b3f573fSAndroid Build Coastguard Worker // (doesn't seem to know about atomic_compare_exchange_strong); so just 793*1b3f573fSAndroid Build Coastguard Worker // for the analyzer, let it think worker is also released in this case. 794*1b3f573fSAndroid Build Coastguard Worker else { dispatch_release(worker); } 795*1b3f573fSAndroid Build Coastguard Worker#endif 796*1b3f573fSAndroid Build Coastguard Worker } 797*1b3f573fSAndroid Build Coastguard Worker 798*1b3f573fSAndroid Build Coastguard Worker#pragma clang diagnostic pop 799*1b3f573fSAndroid Build Coastguard Worker} 800*1b3f573fSAndroid Build Coastguard Worker 801*1b3f573fSAndroid Build Coastguard Workerstatic GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { 802*1b3f573fSAndroid Build Coastguard Worker if (!self->unknownFields_) { 803*1b3f573fSAndroid Build Coastguard Worker self->unknownFields_ = [[GPBUnknownFieldSet alloc] init]; 804*1b3f573fSAndroid Build Coastguard Worker GPBBecomeVisibleToAutocreator(self); 805*1b3f573fSAndroid Build Coastguard Worker } 806*1b3f573fSAndroid Build Coastguard Worker return self->unknownFields_; 807*1b3f573fSAndroid Build Coastguard Worker} 808*1b3f573fSAndroid Build Coastguard Worker 809*1b3f573fSAndroid Build Coastguard Worker@implementation GPBMessage 810*1b3f573fSAndroid Build Coastguard Worker 811*1b3f573fSAndroid Build Coastguard Worker+ (void)initialize { 812*1b3f573fSAndroid Build Coastguard Worker Class pbMessageClass = [GPBMessage class]; 813*1b3f573fSAndroid Build Coastguard Worker if ([self class] == pbMessageClass) { 814*1b3f573fSAndroid Build Coastguard Worker // This is here to start up the "base" class descriptor. 815*1b3f573fSAndroid Build Coastguard Worker [self descriptor]; 816*1b3f573fSAndroid Build Coastguard Worker // Message shares extension method resolving with GPBRootObject so insure 817*1b3f573fSAndroid Build Coastguard Worker // it is started up at the same time. 818*1b3f573fSAndroid Build Coastguard Worker (void)[GPBRootObject class]; 819*1b3f573fSAndroid Build Coastguard Worker } else if ([self superclass] == pbMessageClass) { 820*1b3f573fSAndroid Build Coastguard Worker // This is here to start up all the "message" subclasses. Just needs to be 821*1b3f573fSAndroid Build Coastguard Worker // done for the messages, not any of the subclasses. 822*1b3f573fSAndroid Build Coastguard Worker // This must be done in initialize to enforce thread safety of start up of 823*1b3f573fSAndroid Build Coastguard Worker // the protocol buffer library. 824*1b3f573fSAndroid Build Coastguard Worker // Note: The generated code for -descriptor calls 825*1b3f573fSAndroid Build Coastguard Worker // +[GPBDescriptor allocDescriptorForClass:...], passing the GPBRootObject 826*1b3f573fSAndroid Build Coastguard Worker // subclass for the file. That call chain is what ensures that *Root class 827*1b3f573fSAndroid Build Coastguard Worker // is started up to support extension resolution off the message class 828*1b3f573fSAndroid Build Coastguard Worker // (+resolveClassMethod: below) in a thread safe manner. 829*1b3f573fSAndroid Build Coastguard Worker [self descriptor]; 830*1b3f573fSAndroid Build Coastguard Worker } 831*1b3f573fSAndroid Build Coastguard Worker} 832*1b3f573fSAndroid Build Coastguard Worker 833*1b3f573fSAndroid Build Coastguard Worker+ (instancetype)allocWithZone:(NSZone *)zone { 834*1b3f573fSAndroid Build Coastguard Worker // Override alloc to allocate our classes with the additional storage 835*1b3f573fSAndroid Build Coastguard Worker // required for the instance variables. 836*1b3f573fSAndroid Build Coastguard Worker GPBDescriptor *descriptor = [self descriptor]; 837*1b3f573fSAndroid Build Coastguard Worker return NSAllocateObject(self, descriptor->storageSize_, zone); 838*1b3f573fSAndroid Build Coastguard Worker} 839*1b3f573fSAndroid Build Coastguard Worker 840*1b3f573fSAndroid Build Coastguard Worker+ (instancetype)alloc { 841*1b3f573fSAndroid Build Coastguard Worker return [self allocWithZone:nil]; 842*1b3f573fSAndroid Build Coastguard Worker} 843*1b3f573fSAndroid Build Coastguard Worker 844*1b3f573fSAndroid Build Coastguard Worker+ (GPBDescriptor *)descriptor { 845*1b3f573fSAndroid Build Coastguard Worker // This is thread safe because it is called from +initialize. 846*1b3f573fSAndroid Build Coastguard Worker static GPBDescriptor *descriptor = NULL; 847*1b3f573fSAndroid Build Coastguard Worker static GPBFileDescriptor *fileDescriptor = NULL; 848*1b3f573fSAndroid Build Coastguard Worker if (!descriptor) { 849*1b3f573fSAndroid Build Coastguard Worker // Use a dummy file that marks it as proto2 syntax so when used generically 850*1b3f573fSAndroid Build Coastguard Worker // it supports unknowns/etc. 851*1b3f573fSAndroid Build Coastguard Worker fileDescriptor = 852*1b3f573fSAndroid Build Coastguard Worker [[GPBFileDescriptor alloc] initWithPackage:@"internal" 853*1b3f573fSAndroid Build Coastguard Worker syntax:GPBFileSyntaxProto2]; 854*1b3f573fSAndroid Build Coastguard Worker 855*1b3f573fSAndroid Build Coastguard Worker descriptor = [GPBDescriptor allocDescriptorForClass:[GPBMessage class] 856*1b3f573fSAndroid Build Coastguard Worker rootClass:Nil 857*1b3f573fSAndroid Build Coastguard Worker file:fileDescriptor 858*1b3f573fSAndroid Build Coastguard Worker fields:NULL 859*1b3f573fSAndroid Build Coastguard Worker fieldCount:0 860*1b3f573fSAndroid Build Coastguard Worker storageSize:0 861*1b3f573fSAndroid Build Coastguard Worker flags:0]; 862*1b3f573fSAndroid Build Coastguard Worker } 863*1b3f573fSAndroid Build Coastguard Worker return descriptor; 864*1b3f573fSAndroid Build Coastguard Worker} 865*1b3f573fSAndroid Build Coastguard Worker 866*1b3f573fSAndroid Build Coastguard Worker+ (instancetype)message { 867*1b3f573fSAndroid Build Coastguard Worker return [[[self alloc] init] autorelease]; 868*1b3f573fSAndroid Build Coastguard Worker} 869*1b3f573fSAndroid Build Coastguard Worker 870*1b3f573fSAndroid Build Coastguard Worker- (instancetype)init { 871*1b3f573fSAndroid Build Coastguard Worker if ((self = [super init])) { 872*1b3f573fSAndroid Build Coastguard Worker messageStorage_ = (GPBMessage_StoragePtr)( 873*1b3f573fSAndroid Build Coastguard Worker ((uint8_t *)self) + class_getInstanceSize([self class])); 874*1b3f573fSAndroid Build Coastguard Worker } 875*1b3f573fSAndroid Build Coastguard Worker 876*1b3f573fSAndroid Build Coastguard Worker return self; 877*1b3f573fSAndroid Build Coastguard Worker} 878*1b3f573fSAndroid Build Coastguard Worker 879*1b3f573fSAndroid Build Coastguard Worker- (instancetype)initWithData:(NSData *)data error:(NSError **)errorPtr { 880*1b3f573fSAndroid Build Coastguard Worker return [self initWithData:data extensionRegistry:nil error:errorPtr]; 881*1b3f573fSAndroid Build Coastguard Worker} 882*1b3f573fSAndroid Build Coastguard Worker 883*1b3f573fSAndroid Build Coastguard Worker- (instancetype)initWithData:(NSData *)data 884*1b3f573fSAndroid Build Coastguard Worker extensionRegistry:(GPBExtensionRegistry *)extensionRegistry 885*1b3f573fSAndroid Build Coastguard Worker error:(NSError **)errorPtr { 886*1b3f573fSAndroid Build Coastguard Worker if ((self = [self init])) { 887*1b3f573fSAndroid Build Coastguard Worker @try { 888*1b3f573fSAndroid Build Coastguard Worker [self mergeFromData:data extensionRegistry:extensionRegistry]; 889*1b3f573fSAndroid Build Coastguard Worker if (errorPtr) { 890*1b3f573fSAndroid Build Coastguard Worker *errorPtr = nil; 891*1b3f573fSAndroid Build Coastguard Worker } 892*1b3f573fSAndroid Build Coastguard Worker } 893*1b3f573fSAndroid Build Coastguard Worker @catch (NSException *exception) { 894*1b3f573fSAndroid Build Coastguard Worker [self release]; 895*1b3f573fSAndroid Build Coastguard Worker self = nil; 896*1b3f573fSAndroid Build Coastguard Worker if (errorPtr) { 897*1b3f573fSAndroid Build Coastguard Worker *errorPtr = ErrorFromException(exception); 898*1b3f573fSAndroid Build Coastguard Worker } 899*1b3f573fSAndroid Build Coastguard Worker } 900*1b3f573fSAndroid Build Coastguard Worker#ifdef DEBUG 901*1b3f573fSAndroid Build Coastguard Worker if (self && !self.initialized) { 902*1b3f573fSAndroid Build Coastguard Worker [self release]; 903*1b3f573fSAndroid Build Coastguard Worker self = nil; 904*1b3f573fSAndroid Build Coastguard Worker if (errorPtr) { 905*1b3f573fSAndroid Build Coastguard Worker *errorPtr = MessageError(GPBMessageErrorCodeMissingRequiredField, nil); 906*1b3f573fSAndroid Build Coastguard Worker } 907*1b3f573fSAndroid Build Coastguard Worker } 908*1b3f573fSAndroid Build Coastguard Worker#endif 909*1b3f573fSAndroid Build Coastguard Worker } 910*1b3f573fSAndroid Build Coastguard Worker return self; 911*1b3f573fSAndroid Build Coastguard Worker} 912*1b3f573fSAndroid Build Coastguard Worker 913*1b3f573fSAndroid Build Coastguard Worker- (instancetype)initWithCodedInputStream:(GPBCodedInputStream *)input 914*1b3f573fSAndroid Build Coastguard Worker extensionRegistry: 915*1b3f573fSAndroid Build Coastguard Worker (GPBExtensionRegistry *)extensionRegistry 916*1b3f573fSAndroid Build Coastguard Worker error:(NSError **)errorPtr { 917*1b3f573fSAndroid Build Coastguard Worker if ((self = [self init])) { 918*1b3f573fSAndroid Build Coastguard Worker @try { 919*1b3f573fSAndroid Build Coastguard Worker [self mergeFromCodedInputStream:input extensionRegistry:extensionRegistry]; 920*1b3f573fSAndroid Build Coastguard Worker if (errorPtr) { 921*1b3f573fSAndroid Build Coastguard Worker *errorPtr = nil; 922*1b3f573fSAndroid Build Coastguard Worker } 923*1b3f573fSAndroid Build Coastguard Worker } 924*1b3f573fSAndroid Build Coastguard Worker @catch (NSException *exception) { 925*1b3f573fSAndroid Build Coastguard Worker [self release]; 926*1b3f573fSAndroid Build Coastguard Worker self = nil; 927*1b3f573fSAndroid Build Coastguard Worker if (errorPtr) { 928*1b3f573fSAndroid Build Coastguard Worker *errorPtr = ErrorFromException(exception); 929*1b3f573fSAndroid Build Coastguard Worker } 930*1b3f573fSAndroid Build Coastguard Worker } 931*1b3f573fSAndroid Build Coastguard Worker#ifdef DEBUG 932*1b3f573fSAndroid Build Coastguard Worker if (self && !self.initialized) { 933*1b3f573fSAndroid Build Coastguard Worker [self release]; 934*1b3f573fSAndroid Build Coastguard Worker self = nil; 935*1b3f573fSAndroid Build Coastguard Worker if (errorPtr) { 936*1b3f573fSAndroid Build Coastguard Worker *errorPtr = MessageError(GPBMessageErrorCodeMissingRequiredField, nil); 937*1b3f573fSAndroid Build Coastguard Worker } 938*1b3f573fSAndroid Build Coastguard Worker } 939*1b3f573fSAndroid Build Coastguard Worker#endif 940*1b3f573fSAndroid Build Coastguard Worker } 941*1b3f573fSAndroid Build Coastguard Worker return self; 942*1b3f573fSAndroid Build Coastguard Worker} 943*1b3f573fSAndroid Build Coastguard Worker 944*1b3f573fSAndroid Build Coastguard Worker- (void)dealloc { 945*1b3f573fSAndroid Build Coastguard Worker [self internalClear:NO]; 946*1b3f573fSAndroid Build Coastguard Worker NSCAssert(!autocreator_, @"Autocreator was not cleared before dealloc."); 947*1b3f573fSAndroid Build Coastguard Worker if (readOnlySemaphore_) { 948*1b3f573fSAndroid Build Coastguard Worker dispatch_release(readOnlySemaphore_); 949*1b3f573fSAndroid Build Coastguard Worker } 950*1b3f573fSAndroid Build Coastguard Worker [super dealloc]; 951*1b3f573fSAndroid Build Coastguard Worker} 952*1b3f573fSAndroid Build Coastguard Worker 953*1b3f573fSAndroid Build Coastguard Worker- (void)copyFieldsInto:(GPBMessage *)message 954*1b3f573fSAndroid Build Coastguard Worker zone:(NSZone *)zone 955*1b3f573fSAndroid Build Coastguard Worker descriptor:(GPBDescriptor *)descriptor { 956*1b3f573fSAndroid Build Coastguard Worker // Copy all the storage... 957*1b3f573fSAndroid Build Coastguard Worker memcpy(message->messageStorage_, messageStorage_, descriptor->storageSize_); 958*1b3f573fSAndroid Build Coastguard Worker 959*1b3f573fSAndroid Build Coastguard Worker // Loop over the fields doing fixup... 960*1b3f573fSAndroid Build Coastguard Worker for (GPBFieldDescriptor *field in descriptor->fields_) { 961*1b3f573fSAndroid Build Coastguard Worker if (GPBFieldIsMapOrArray(field)) { 962*1b3f573fSAndroid Build Coastguard Worker id value = GPBGetObjectIvarWithFieldNoAutocreate(self, field); 963*1b3f573fSAndroid Build Coastguard Worker if (value) { 964*1b3f573fSAndroid Build Coastguard Worker // We need to copy the array/map, but the catch is for message fields, 965*1b3f573fSAndroid Build Coastguard Worker // we also need to ensure all the messages as those need copying also. 966*1b3f573fSAndroid Build Coastguard Worker id newValue; 967*1b3f573fSAndroid Build Coastguard Worker if (GPBFieldDataTypeIsMessage(field)) { 968*1b3f573fSAndroid Build Coastguard Worker if (field.fieldType == GPBFieldTypeRepeated) { 969*1b3f573fSAndroid Build Coastguard Worker NSArray *existingArray = (NSArray *)value; 970*1b3f573fSAndroid Build Coastguard Worker NSMutableArray *newArray = 971*1b3f573fSAndroid Build Coastguard Worker [[NSMutableArray alloc] initWithCapacity:existingArray.count]; 972*1b3f573fSAndroid Build Coastguard Worker newValue = newArray; 973*1b3f573fSAndroid Build Coastguard Worker for (GPBMessage *msg in existingArray) { 974*1b3f573fSAndroid Build Coastguard Worker GPBMessage *copiedMsg = [msg copyWithZone:zone]; 975*1b3f573fSAndroid Build Coastguard Worker [newArray addObject:copiedMsg]; 976*1b3f573fSAndroid Build Coastguard Worker [copiedMsg release]; 977*1b3f573fSAndroid Build Coastguard Worker } 978*1b3f573fSAndroid Build Coastguard Worker } else { 979*1b3f573fSAndroid Build Coastguard Worker if (field.mapKeyDataType == GPBDataTypeString) { 980*1b3f573fSAndroid Build Coastguard Worker // Map is an NSDictionary. 981*1b3f573fSAndroid Build Coastguard Worker NSDictionary *existingDict = value; 982*1b3f573fSAndroid Build Coastguard Worker NSMutableDictionary *newDict = [[NSMutableDictionary alloc] 983*1b3f573fSAndroid Build Coastguard Worker initWithCapacity:existingDict.count]; 984*1b3f573fSAndroid Build Coastguard Worker newValue = newDict; 985*1b3f573fSAndroid Build Coastguard Worker [existingDict enumerateKeysAndObjectsUsingBlock:^(NSString *key, 986*1b3f573fSAndroid Build Coastguard Worker GPBMessage *msg, 987*1b3f573fSAndroid Build Coastguard Worker BOOL *stop) { 988*1b3f573fSAndroid Build Coastguard Worker#pragma unused(stop) 989*1b3f573fSAndroid Build Coastguard Worker GPBMessage *copiedMsg = [msg copyWithZone:zone]; 990*1b3f573fSAndroid Build Coastguard Worker [newDict setObject:copiedMsg forKey:key]; 991*1b3f573fSAndroid Build Coastguard Worker [copiedMsg release]; 992*1b3f573fSAndroid Build Coastguard Worker }]; 993*1b3f573fSAndroid Build Coastguard Worker } else { 994*1b3f573fSAndroid Build Coastguard Worker // Is one of the GPB*ObjectDictionary classes. Type doesn't 995*1b3f573fSAndroid Build Coastguard Worker // matter, just need one to invoke the selector. 996*1b3f573fSAndroid Build Coastguard Worker GPBInt32ObjectDictionary *existingDict = value; 997*1b3f573fSAndroid Build Coastguard Worker newValue = [existingDict deepCopyWithZone:zone]; 998*1b3f573fSAndroid Build Coastguard Worker } 999*1b3f573fSAndroid Build Coastguard Worker } 1000*1b3f573fSAndroid Build Coastguard Worker } else { 1001*1b3f573fSAndroid Build Coastguard Worker // Not messages (but is a map/array)... 1002*1b3f573fSAndroid Build Coastguard Worker if (field.fieldType == GPBFieldTypeRepeated) { 1003*1b3f573fSAndroid Build Coastguard Worker if (GPBFieldDataTypeIsObject(field)) { 1004*1b3f573fSAndroid Build Coastguard Worker // NSArray 1005*1b3f573fSAndroid Build Coastguard Worker newValue = [value mutableCopyWithZone:zone]; 1006*1b3f573fSAndroid Build Coastguard Worker } else { 1007*1b3f573fSAndroid Build Coastguard Worker // GPB*Array 1008*1b3f573fSAndroid Build Coastguard Worker newValue = [value copyWithZone:zone]; 1009*1b3f573fSAndroid Build Coastguard Worker } 1010*1b3f573fSAndroid Build Coastguard Worker } else { 1011*1b3f573fSAndroid Build Coastguard Worker if ((field.mapKeyDataType == GPBDataTypeString) && 1012*1b3f573fSAndroid Build Coastguard Worker GPBFieldDataTypeIsObject(field)) { 1013*1b3f573fSAndroid Build Coastguard Worker // NSDictionary 1014*1b3f573fSAndroid Build Coastguard Worker newValue = [value mutableCopyWithZone:zone]; 1015*1b3f573fSAndroid Build Coastguard Worker } else { 1016*1b3f573fSAndroid Build Coastguard Worker // Is one of the GPB*Dictionary classes. Type doesn't matter, 1017*1b3f573fSAndroid Build Coastguard Worker // just need one to invoke the selector. 1018*1b3f573fSAndroid Build Coastguard Worker GPBInt32Int32Dictionary *existingDict = value; 1019*1b3f573fSAndroid Build Coastguard Worker newValue = [existingDict copyWithZone:zone]; 1020*1b3f573fSAndroid Build Coastguard Worker } 1021*1b3f573fSAndroid Build Coastguard Worker } 1022*1b3f573fSAndroid Build Coastguard Worker } 1023*1b3f573fSAndroid Build Coastguard Worker // We retain here because the memcpy picked up the pointer value and 1024*1b3f573fSAndroid Build Coastguard Worker // the next call to SetRetainedObject... will release the current value. 1025*1b3f573fSAndroid Build Coastguard Worker [value retain]; 1026*1b3f573fSAndroid Build Coastguard Worker GPBSetRetainedObjectIvarWithFieldPrivate(message, field, newValue); 1027*1b3f573fSAndroid Build Coastguard Worker } 1028*1b3f573fSAndroid Build Coastguard Worker } else if (GPBFieldDataTypeIsMessage(field)) { 1029*1b3f573fSAndroid Build Coastguard Worker // For object types, if we have a value, copy it. If we don't, 1030*1b3f573fSAndroid Build Coastguard Worker // zero it to remove the pointer to something that was autocreated 1031*1b3f573fSAndroid Build Coastguard Worker // (and the ptr just got memcpyed). 1032*1b3f573fSAndroid Build Coastguard Worker if (GPBGetHasIvarField(self, field)) { 1033*1b3f573fSAndroid Build Coastguard Worker GPBMessage *value = GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1034*1b3f573fSAndroid Build Coastguard Worker GPBMessage *newValue = [value copyWithZone:zone]; 1035*1b3f573fSAndroid Build Coastguard Worker // We retain here because the memcpy picked up the pointer value and 1036*1b3f573fSAndroid Build Coastguard Worker // the next call to SetRetainedObject... will release the current value. 1037*1b3f573fSAndroid Build Coastguard Worker [value retain]; 1038*1b3f573fSAndroid Build Coastguard Worker GPBSetRetainedObjectIvarWithFieldPrivate(message, field, newValue); 1039*1b3f573fSAndroid Build Coastguard Worker } else { 1040*1b3f573fSAndroid Build Coastguard Worker uint8_t *storage = (uint8_t *)message->messageStorage_; 1041*1b3f573fSAndroid Build Coastguard Worker id *typePtr = (id *)&storage[field->description_->offset]; 1042*1b3f573fSAndroid Build Coastguard Worker *typePtr = NULL; 1043*1b3f573fSAndroid Build Coastguard Worker } 1044*1b3f573fSAndroid Build Coastguard Worker } else if (GPBFieldDataTypeIsObject(field) && 1045*1b3f573fSAndroid Build Coastguard Worker GPBGetHasIvarField(self, field)) { 1046*1b3f573fSAndroid Build Coastguard Worker // A set string/data value (message picked off above), copy it. 1047*1b3f573fSAndroid Build Coastguard Worker id value = GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1048*1b3f573fSAndroid Build Coastguard Worker id newValue = [value copyWithZone:zone]; 1049*1b3f573fSAndroid Build Coastguard Worker // We retain here because the memcpy picked up the pointer value and 1050*1b3f573fSAndroid Build Coastguard Worker // the next call to SetRetainedObject... will release the current value. 1051*1b3f573fSAndroid Build Coastguard Worker [value retain]; 1052*1b3f573fSAndroid Build Coastguard Worker GPBSetRetainedObjectIvarWithFieldPrivate(message, field, newValue); 1053*1b3f573fSAndroid Build Coastguard Worker } else { 1054*1b3f573fSAndroid Build Coastguard Worker // memcpy took care of the rest of the primitive fields if they were set. 1055*1b3f573fSAndroid Build Coastguard Worker } 1056*1b3f573fSAndroid Build Coastguard Worker } // for (field in descriptor->fields_) 1057*1b3f573fSAndroid Build Coastguard Worker} 1058*1b3f573fSAndroid Build Coastguard Worker 1059*1b3f573fSAndroid Build Coastguard Worker- (id)copyWithZone:(NSZone *)zone { 1060*1b3f573fSAndroid Build Coastguard Worker GPBDescriptor *descriptor = [self descriptor]; 1061*1b3f573fSAndroid Build Coastguard Worker GPBMessage *result = [[descriptor.messageClass allocWithZone:zone] init]; 1062*1b3f573fSAndroid Build Coastguard Worker 1063*1b3f573fSAndroid Build Coastguard Worker [self copyFieldsInto:result zone:zone descriptor:descriptor]; 1064*1b3f573fSAndroid Build Coastguard Worker // Make immutable copies of the extra bits. 1065*1b3f573fSAndroid Build Coastguard Worker result->unknownFields_ = [unknownFields_ copyWithZone:zone]; 1066*1b3f573fSAndroid Build Coastguard Worker result->extensionMap_ = CloneExtensionMap(extensionMap_, zone); 1067*1b3f573fSAndroid Build Coastguard Worker return result; 1068*1b3f573fSAndroid Build Coastguard Worker} 1069*1b3f573fSAndroid Build Coastguard Worker 1070*1b3f573fSAndroid Build Coastguard Worker- (void)clear { 1071*1b3f573fSAndroid Build Coastguard Worker [self internalClear:YES]; 1072*1b3f573fSAndroid Build Coastguard Worker} 1073*1b3f573fSAndroid Build Coastguard Worker 1074*1b3f573fSAndroid Build Coastguard Worker- (void)internalClear:(BOOL)zeroStorage { 1075*1b3f573fSAndroid Build Coastguard Worker GPBDescriptor *descriptor = [self descriptor]; 1076*1b3f573fSAndroid Build Coastguard Worker for (GPBFieldDescriptor *field in descriptor->fields_) { 1077*1b3f573fSAndroid Build Coastguard Worker if (GPBFieldIsMapOrArray(field)) { 1078*1b3f573fSAndroid Build Coastguard Worker id arrayOrMap = GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1079*1b3f573fSAndroid Build Coastguard Worker if (arrayOrMap) { 1080*1b3f573fSAndroid Build Coastguard Worker if (field.fieldType == GPBFieldTypeRepeated) { 1081*1b3f573fSAndroid Build Coastguard Worker if (GPBFieldDataTypeIsObject(field)) { 1082*1b3f573fSAndroid Build Coastguard Worker if ([arrayOrMap isKindOfClass:[GPBAutocreatedArray class]]) { 1083*1b3f573fSAndroid Build Coastguard Worker GPBAutocreatedArray *autoArray = arrayOrMap; 1084*1b3f573fSAndroid Build Coastguard Worker if (autoArray->_autocreator == self) { 1085*1b3f573fSAndroid Build Coastguard Worker autoArray->_autocreator = nil; 1086*1b3f573fSAndroid Build Coastguard Worker } 1087*1b3f573fSAndroid Build Coastguard Worker } 1088*1b3f573fSAndroid Build Coastguard Worker } else { 1089*1b3f573fSAndroid Build Coastguard Worker // Type doesn't matter, it is a GPB*Array. 1090*1b3f573fSAndroid Build Coastguard Worker GPBInt32Array *gpbArray = arrayOrMap; 1091*1b3f573fSAndroid Build Coastguard Worker if (gpbArray->_autocreator == self) { 1092*1b3f573fSAndroid Build Coastguard Worker gpbArray->_autocreator = nil; 1093*1b3f573fSAndroid Build Coastguard Worker } 1094*1b3f573fSAndroid Build Coastguard Worker } 1095*1b3f573fSAndroid Build Coastguard Worker } else { 1096*1b3f573fSAndroid Build Coastguard Worker if ((field.mapKeyDataType == GPBDataTypeString) && 1097*1b3f573fSAndroid Build Coastguard Worker GPBFieldDataTypeIsObject(field)) { 1098*1b3f573fSAndroid Build Coastguard Worker if ([arrayOrMap isKindOfClass:[GPBAutocreatedDictionary class]]) { 1099*1b3f573fSAndroid Build Coastguard Worker GPBAutocreatedDictionary *autoDict = arrayOrMap; 1100*1b3f573fSAndroid Build Coastguard Worker if (autoDict->_autocreator == self) { 1101*1b3f573fSAndroid Build Coastguard Worker autoDict->_autocreator = nil; 1102*1b3f573fSAndroid Build Coastguard Worker } 1103*1b3f573fSAndroid Build Coastguard Worker } 1104*1b3f573fSAndroid Build Coastguard Worker } else { 1105*1b3f573fSAndroid Build Coastguard Worker // Type doesn't matter, it is a GPB*Dictionary. 1106*1b3f573fSAndroid Build Coastguard Worker GPBInt32Int32Dictionary *gpbDict = arrayOrMap; 1107*1b3f573fSAndroid Build Coastguard Worker if (gpbDict->_autocreator == self) { 1108*1b3f573fSAndroid Build Coastguard Worker gpbDict->_autocreator = nil; 1109*1b3f573fSAndroid Build Coastguard Worker } 1110*1b3f573fSAndroid Build Coastguard Worker } 1111*1b3f573fSAndroid Build Coastguard Worker } 1112*1b3f573fSAndroid Build Coastguard Worker [arrayOrMap release]; 1113*1b3f573fSAndroid Build Coastguard Worker } 1114*1b3f573fSAndroid Build Coastguard Worker } else if (GPBFieldDataTypeIsMessage(field)) { 1115*1b3f573fSAndroid Build Coastguard Worker GPBClearAutocreatedMessageIvarWithField(self, field); 1116*1b3f573fSAndroid Build Coastguard Worker GPBMessage *value = GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1117*1b3f573fSAndroid Build Coastguard Worker [value release]; 1118*1b3f573fSAndroid Build Coastguard Worker } else if (GPBFieldDataTypeIsObject(field) && 1119*1b3f573fSAndroid Build Coastguard Worker GPBGetHasIvarField(self, field)) { 1120*1b3f573fSAndroid Build Coastguard Worker id value = GPBGetObjectIvarWithField(self, field); 1121*1b3f573fSAndroid Build Coastguard Worker [value release]; 1122*1b3f573fSAndroid Build Coastguard Worker } 1123*1b3f573fSAndroid Build Coastguard Worker } 1124*1b3f573fSAndroid Build Coastguard Worker 1125*1b3f573fSAndroid Build Coastguard Worker // GPBClearMessageAutocreator() expects that its caller has already been 1126*1b3f573fSAndroid Build Coastguard Worker // removed from autocreatedExtensionMap_ so we set to nil first. 1127*1b3f573fSAndroid Build Coastguard Worker NSArray *autocreatedValues = [autocreatedExtensionMap_ allValues]; 1128*1b3f573fSAndroid Build Coastguard Worker [autocreatedExtensionMap_ release]; 1129*1b3f573fSAndroid Build Coastguard Worker autocreatedExtensionMap_ = nil; 1130*1b3f573fSAndroid Build Coastguard Worker 1131*1b3f573fSAndroid Build Coastguard Worker // Since we're clearing all of our extensions, make sure that we clear the 1132*1b3f573fSAndroid Build Coastguard Worker // autocreator on any that we've created so they no longer refer to us. 1133*1b3f573fSAndroid Build Coastguard Worker for (GPBMessage *value in autocreatedValues) { 1134*1b3f573fSAndroid Build Coastguard Worker NSCAssert(GPBWasMessageAutocreatedBy(value, self), 1135*1b3f573fSAndroid Build Coastguard Worker @"Autocreated extension does not refer back to self."); 1136*1b3f573fSAndroid Build Coastguard Worker GPBClearMessageAutocreator(value); 1137*1b3f573fSAndroid Build Coastguard Worker } 1138*1b3f573fSAndroid Build Coastguard Worker 1139*1b3f573fSAndroid Build Coastguard Worker [extensionMap_ release]; 1140*1b3f573fSAndroid Build Coastguard Worker extensionMap_ = nil; 1141*1b3f573fSAndroid Build Coastguard Worker [unknownFields_ release]; 1142*1b3f573fSAndroid Build Coastguard Worker unknownFields_ = nil; 1143*1b3f573fSAndroid Build Coastguard Worker 1144*1b3f573fSAndroid Build Coastguard Worker // Note that clearing does not affect autocreator_. If we are being cleared 1145*1b3f573fSAndroid Build Coastguard Worker // because of a dealloc, then autocreator_ should be nil anyway. If we are 1146*1b3f573fSAndroid Build Coastguard Worker // being cleared because someone explicitly clears us, we don't want to 1147*1b3f573fSAndroid Build Coastguard Worker // sever our relationship with our autocreator. 1148*1b3f573fSAndroid Build Coastguard Worker 1149*1b3f573fSAndroid Build Coastguard Worker if (zeroStorage) { 1150*1b3f573fSAndroid Build Coastguard Worker memset(messageStorage_, 0, descriptor->storageSize_); 1151*1b3f573fSAndroid Build Coastguard Worker } 1152*1b3f573fSAndroid Build Coastguard Worker} 1153*1b3f573fSAndroid Build Coastguard Worker 1154*1b3f573fSAndroid Build Coastguard Worker- (BOOL)isInitialized { 1155*1b3f573fSAndroid Build Coastguard Worker GPBDescriptor *descriptor = [self descriptor]; 1156*1b3f573fSAndroid Build Coastguard Worker for (GPBFieldDescriptor *field in descriptor->fields_) { 1157*1b3f573fSAndroid Build Coastguard Worker if (field.isRequired) { 1158*1b3f573fSAndroid Build Coastguard Worker if (!GPBGetHasIvarField(self, field)) { 1159*1b3f573fSAndroid Build Coastguard Worker return NO; 1160*1b3f573fSAndroid Build Coastguard Worker } 1161*1b3f573fSAndroid Build Coastguard Worker } 1162*1b3f573fSAndroid Build Coastguard Worker if (GPBFieldDataTypeIsMessage(field)) { 1163*1b3f573fSAndroid Build Coastguard Worker GPBFieldType fieldType = field.fieldType; 1164*1b3f573fSAndroid Build Coastguard Worker if (fieldType == GPBFieldTypeSingle) { 1165*1b3f573fSAndroid Build Coastguard Worker if (field.isRequired) { 1166*1b3f573fSAndroid Build Coastguard Worker GPBMessage *message = GPBGetMessageMessageField(self, field); 1167*1b3f573fSAndroid Build Coastguard Worker if (!message.initialized) { 1168*1b3f573fSAndroid Build Coastguard Worker return NO; 1169*1b3f573fSAndroid Build Coastguard Worker } 1170*1b3f573fSAndroid Build Coastguard Worker } else { 1171*1b3f573fSAndroid Build Coastguard Worker NSAssert(field.isOptional, 1172*1b3f573fSAndroid Build Coastguard Worker @"%@: Single message field %@ not required or optional?", 1173*1b3f573fSAndroid Build Coastguard Worker [self class], field.name); 1174*1b3f573fSAndroid Build Coastguard Worker if (GPBGetHasIvarField(self, field)) { 1175*1b3f573fSAndroid Build Coastguard Worker GPBMessage *message = GPBGetMessageMessageField(self, field); 1176*1b3f573fSAndroid Build Coastguard Worker if (!message.initialized) { 1177*1b3f573fSAndroid Build Coastguard Worker return NO; 1178*1b3f573fSAndroid Build Coastguard Worker } 1179*1b3f573fSAndroid Build Coastguard Worker } 1180*1b3f573fSAndroid Build Coastguard Worker } 1181*1b3f573fSAndroid Build Coastguard Worker } else if (fieldType == GPBFieldTypeRepeated) { 1182*1b3f573fSAndroid Build Coastguard Worker NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1183*1b3f573fSAndroid Build Coastguard Worker for (GPBMessage *message in array) { 1184*1b3f573fSAndroid Build Coastguard Worker if (!message.initialized) { 1185*1b3f573fSAndroid Build Coastguard Worker return NO; 1186*1b3f573fSAndroid Build Coastguard Worker } 1187*1b3f573fSAndroid Build Coastguard Worker } 1188*1b3f573fSAndroid Build Coastguard Worker } else { // fieldType == GPBFieldTypeMap 1189*1b3f573fSAndroid Build Coastguard Worker if (field.mapKeyDataType == GPBDataTypeString) { 1190*1b3f573fSAndroid Build Coastguard Worker NSDictionary *map = 1191*1b3f573fSAndroid Build Coastguard Worker GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1192*1b3f573fSAndroid Build Coastguard Worker if (map && !GPBDictionaryIsInitializedInternalHelper(map, field)) { 1193*1b3f573fSAndroid Build Coastguard Worker return NO; 1194*1b3f573fSAndroid Build Coastguard Worker } 1195*1b3f573fSAndroid Build Coastguard Worker } else { 1196*1b3f573fSAndroid Build Coastguard Worker // Real type is GPB*ObjectDictionary, exact type doesn't matter. 1197*1b3f573fSAndroid Build Coastguard Worker GPBInt32ObjectDictionary *map = 1198*1b3f573fSAndroid Build Coastguard Worker GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1199*1b3f573fSAndroid Build Coastguard Worker if (map && ![map isInitialized]) { 1200*1b3f573fSAndroid Build Coastguard Worker return NO; 1201*1b3f573fSAndroid Build Coastguard Worker } 1202*1b3f573fSAndroid Build Coastguard Worker } 1203*1b3f573fSAndroid Build Coastguard Worker } 1204*1b3f573fSAndroid Build Coastguard Worker } 1205*1b3f573fSAndroid Build Coastguard Worker } 1206*1b3f573fSAndroid Build Coastguard Worker 1207*1b3f573fSAndroid Build Coastguard Worker __block BOOL result = YES; 1208*1b3f573fSAndroid Build Coastguard Worker [extensionMap_ 1209*1b3f573fSAndroid Build Coastguard Worker enumerateKeysAndObjectsUsingBlock:^(GPBExtensionDescriptor *extension, 1210*1b3f573fSAndroid Build Coastguard Worker id obj, 1211*1b3f573fSAndroid Build Coastguard Worker BOOL *stop) { 1212*1b3f573fSAndroid Build Coastguard Worker if (GPBExtensionIsMessage(extension)) { 1213*1b3f573fSAndroid Build Coastguard Worker if (extension.isRepeated) { 1214*1b3f573fSAndroid Build Coastguard Worker for (GPBMessage *msg in obj) { 1215*1b3f573fSAndroid Build Coastguard Worker if (!msg.initialized) { 1216*1b3f573fSAndroid Build Coastguard Worker result = NO; 1217*1b3f573fSAndroid Build Coastguard Worker *stop = YES; 1218*1b3f573fSAndroid Build Coastguard Worker break; 1219*1b3f573fSAndroid Build Coastguard Worker } 1220*1b3f573fSAndroid Build Coastguard Worker } 1221*1b3f573fSAndroid Build Coastguard Worker } else { 1222*1b3f573fSAndroid Build Coastguard Worker GPBMessage *asMsg = obj; 1223*1b3f573fSAndroid Build Coastguard Worker if (!asMsg.initialized) { 1224*1b3f573fSAndroid Build Coastguard Worker result = NO; 1225*1b3f573fSAndroid Build Coastguard Worker *stop = YES; 1226*1b3f573fSAndroid Build Coastguard Worker } 1227*1b3f573fSAndroid Build Coastguard Worker } 1228*1b3f573fSAndroid Build Coastguard Worker } 1229*1b3f573fSAndroid Build Coastguard Worker }]; 1230*1b3f573fSAndroid Build Coastguard Worker return result; 1231*1b3f573fSAndroid Build Coastguard Worker} 1232*1b3f573fSAndroid Build Coastguard Worker 1233*1b3f573fSAndroid Build Coastguard Worker- (GPBDescriptor *)descriptor { 1234*1b3f573fSAndroid Build Coastguard Worker return [[self class] descriptor]; 1235*1b3f573fSAndroid Build Coastguard Worker} 1236*1b3f573fSAndroid Build Coastguard Worker 1237*1b3f573fSAndroid Build Coastguard Worker- (NSData *)data { 1238*1b3f573fSAndroid Build Coastguard Worker#ifdef DEBUG 1239*1b3f573fSAndroid Build Coastguard Worker if (!self.initialized) { 1240*1b3f573fSAndroid Build Coastguard Worker return nil; 1241*1b3f573fSAndroid Build Coastguard Worker } 1242*1b3f573fSAndroid Build Coastguard Worker#endif 1243*1b3f573fSAndroid Build Coastguard Worker NSMutableData *data = [NSMutableData dataWithLength:[self serializedSize]]; 1244*1b3f573fSAndroid Build Coastguard Worker GPBCodedOutputStream *stream = 1245*1b3f573fSAndroid Build Coastguard Worker [[GPBCodedOutputStream alloc] initWithData:data]; 1246*1b3f573fSAndroid Build Coastguard Worker @try { 1247*1b3f573fSAndroid Build Coastguard Worker [self writeToCodedOutputStream:stream]; 1248*1b3f573fSAndroid Build Coastguard Worker } 1249*1b3f573fSAndroid Build Coastguard Worker @catch (NSException *exception) { 1250*1b3f573fSAndroid Build Coastguard Worker // This really shouldn't happen. The only way writeToCodedOutputStream: 1251*1b3f573fSAndroid Build Coastguard Worker // could throw is if something in the library has a bug and the 1252*1b3f573fSAndroid Build Coastguard Worker // serializedSize was wrong. 1253*1b3f573fSAndroid Build Coastguard Worker#ifdef DEBUG 1254*1b3f573fSAndroid Build Coastguard Worker NSLog(@"%@: Internal exception while building message data: %@", 1255*1b3f573fSAndroid Build Coastguard Worker [self class], exception); 1256*1b3f573fSAndroid Build Coastguard Worker#endif 1257*1b3f573fSAndroid Build Coastguard Worker data = nil; 1258*1b3f573fSAndroid Build Coastguard Worker } 1259*1b3f573fSAndroid Build Coastguard Worker [stream release]; 1260*1b3f573fSAndroid Build Coastguard Worker return data; 1261*1b3f573fSAndroid Build Coastguard Worker} 1262*1b3f573fSAndroid Build Coastguard Worker 1263*1b3f573fSAndroid Build Coastguard Worker- (NSData *)delimitedData { 1264*1b3f573fSAndroid Build Coastguard Worker size_t serializedSize = [self serializedSize]; 1265*1b3f573fSAndroid Build Coastguard Worker size_t varintSize = GPBComputeRawVarint32SizeForInteger(serializedSize); 1266*1b3f573fSAndroid Build Coastguard Worker NSMutableData *data = 1267*1b3f573fSAndroid Build Coastguard Worker [NSMutableData dataWithLength:(serializedSize + varintSize)]; 1268*1b3f573fSAndroid Build Coastguard Worker GPBCodedOutputStream *stream = 1269*1b3f573fSAndroid Build Coastguard Worker [[GPBCodedOutputStream alloc] initWithData:data]; 1270*1b3f573fSAndroid Build Coastguard Worker @try { 1271*1b3f573fSAndroid Build Coastguard Worker [self writeDelimitedToCodedOutputStream:stream]; 1272*1b3f573fSAndroid Build Coastguard Worker } 1273*1b3f573fSAndroid Build Coastguard Worker @catch (NSException *exception) { 1274*1b3f573fSAndroid Build Coastguard Worker // This really shouldn't happen. The only way writeToCodedOutputStream: 1275*1b3f573fSAndroid Build Coastguard Worker // could throw is if something in the library has a bug and the 1276*1b3f573fSAndroid Build Coastguard Worker // serializedSize was wrong. 1277*1b3f573fSAndroid Build Coastguard Worker#ifdef DEBUG 1278*1b3f573fSAndroid Build Coastguard Worker NSLog(@"%@: Internal exception while building message delimitedData: %@", 1279*1b3f573fSAndroid Build Coastguard Worker [self class], exception); 1280*1b3f573fSAndroid Build Coastguard Worker#endif 1281*1b3f573fSAndroid Build Coastguard Worker // If it happens, truncate. 1282*1b3f573fSAndroid Build Coastguard Worker data.length = 0; 1283*1b3f573fSAndroid Build Coastguard Worker } 1284*1b3f573fSAndroid Build Coastguard Worker [stream release]; 1285*1b3f573fSAndroid Build Coastguard Worker return data; 1286*1b3f573fSAndroid Build Coastguard Worker} 1287*1b3f573fSAndroid Build Coastguard Worker 1288*1b3f573fSAndroid Build Coastguard Worker- (void)writeToOutputStream:(NSOutputStream *)output { 1289*1b3f573fSAndroid Build Coastguard Worker GPBCodedOutputStream *stream = 1290*1b3f573fSAndroid Build Coastguard Worker [[GPBCodedOutputStream alloc] initWithOutputStream:output]; 1291*1b3f573fSAndroid Build Coastguard Worker [self writeToCodedOutputStream:stream]; 1292*1b3f573fSAndroid Build Coastguard Worker [stream release]; 1293*1b3f573fSAndroid Build Coastguard Worker} 1294*1b3f573fSAndroid Build Coastguard Worker 1295*1b3f573fSAndroid Build Coastguard Worker- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)output { 1296*1b3f573fSAndroid Build Coastguard Worker GPBDescriptor *descriptor = [self descriptor]; 1297*1b3f573fSAndroid Build Coastguard Worker NSArray *fieldsArray = descriptor->fields_; 1298*1b3f573fSAndroid Build Coastguard Worker NSUInteger fieldCount = fieldsArray.count; 1299*1b3f573fSAndroid Build Coastguard Worker const GPBExtensionRange *extensionRanges = descriptor.extensionRanges; 1300*1b3f573fSAndroid Build Coastguard Worker NSUInteger extensionRangesCount = descriptor.extensionRangesCount; 1301*1b3f573fSAndroid Build Coastguard Worker NSArray *sortedExtensions = 1302*1b3f573fSAndroid Build Coastguard Worker [[extensionMap_ allKeys] sortedArrayUsingSelector:@selector(compareByFieldNumber:)]; 1303*1b3f573fSAndroid Build Coastguard Worker for (NSUInteger i = 0, j = 0; i < fieldCount || j < extensionRangesCount;) { 1304*1b3f573fSAndroid Build Coastguard Worker if (i == fieldCount) { 1305*1b3f573fSAndroid Build Coastguard Worker [self writeExtensionsToCodedOutputStream:output 1306*1b3f573fSAndroid Build Coastguard Worker range:extensionRanges[j++] 1307*1b3f573fSAndroid Build Coastguard Worker sortedExtensions:sortedExtensions]; 1308*1b3f573fSAndroid Build Coastguard Worker } else if (j == extensionRangesCount || 1309*1b3f573fSAndroid Build Coastguard Worker GPBFieldNumber(fieldsArray[i]) < extensionRanges[j].start) { 1310*1b3f573fSAndroid Build Coastguard Worker [self writeField:fieldsArray[i++] toCodedOutputStream:output]; 1311*1b3f573fSAndroid Build Coastguard Worker } else { 1312*1b3f573fSAndroid Build Coastguard Worker [self writeExtensionsToCodedOutputStream:output 1313*1b3f573fSAndroid Build Coastguard Worker range:extensionRanges[j++] 1314*1b3f573fSAndroid Build Coastguard Worker sortedExtensions:sortedExtensions]; 1315*1b3f573fSAndroid Build Coastguard Worker } 1316*1b3f573fSAndroid Build Coastguard Worker } 1317*1b3f573fSAndroid Build Coastguard Worker if (descriptor.isWireFormat) { 1318*1b3f573fSAndroid Build Coastguard Worker [unknownFields_ writeAsMessageSetTo:output]; 1319*1b3f573fSAndroid Build Coastguard Worker } else { 1320*1b3f573fSAndroid Build Coastguard Worker [unknownFields_ writeToCodedOutputStream:output]; 1321*1b3f573fSAndroid Build Coastguard Worker } 1322*1b3f573fSAndroid Build Coastguard Worker} 1323*1b3f573fSAndroid Build Coastguard Worker 1324*1b3f573fSAndroid Build Coastguard Worker- (void)writeDelimitedToOutputStream:(NSOutputStream *)output { 1325*1b3f573fSAndroid Build Coastguard Worker GPBCodedOutputStream *codedOutput = 1326*1b3f573fSAndroid Build Coastguard Worker [[GPBCodedOutputStream alloc] initWithOutputStream:output]; 1327*1b3f573fSAndroid Build Coastguard Worker [self writeDelimitedToCodedOutputStream:codedOutput]; 1328*1b3f573fSAndroid Build Coastguard Worker [codedOutput release]; 1329*1b3f573fSAndroid Build Coastguard Worker} 1330*1b3f573fSAndroid Build Coastguard Worker 1331*1b3f573fSAndroid Build Coastguard Worker- (void)writeDelimitedToCodedOutputStream:(GPBCodedOutputStream *)output { 1332*1b3f573fSAndroid Build Coastguard Worker [output writeRawVarintSizeTAs32:[self serializedSize]]; 1333*1b3f573fSAndroid Build Coastguard Worker [self writeToCodedOutputStream:output]; 1334*1b3f573fSAndroid Build Coastguard Worker} 1335*1b3f573fSAndroid Build Coastguard Worker 1336*1b3f573fSAndroid Build Coastguard Worker- (void)writeField:(GPBFieldDescriptor *)field 1337*1b3f573fSAndroid Build Coastguard Worker toCodedOutputStream:(GPBCodedOutputStream *)output { 1338*1b3f573fSAndroid Build Coastguard Worker GPBFieldType fieldType = field.fieldType; 1339*1b3f573fSAndroid Build Coastguard Worker if (fieldType == GPBFieldTypeSingle) { 1340*1b3f573fSAndroid Build Coastguard Worker BOOL has = GPBGetHasIvarField(self, field); 1341*1b3f573fSAndroid Build Coastguard Worker if (!has) { 1342*1b3f573fSAndroid Build Coastguard Worker return; 1343*1b3f573fSAndroid Build Coastguard Worker } 1344*1b3f573fSAndroid Build Coastguard Worker } 1345*1b3f573fSAndroid Build Coastguard Worker uint32_t fieldNumber = GPBFieldNumber(field); 1346*1b3f573fSAndroid Build Coastguard Worker 1347*1b3f573fSAndroid Build Coastguard Worker//%PDDM-DEFINE FIELD_CASE(TYPE, REAL_TYPE) 1348*1b3f573fSAndroid Build Coastguard Worker//%FIELD_CASE_FULL(TYPE, REAL_TYPE, REAL_TYPE) 1349*1b3f573fSAndroid Build Coastguard Worker//%PDDM-DEFINE FIELD_CASE_FULL(TYPE, REAL_TYPE, ARRAY_TYPE) 1350*1b3f573fSAndroid Build Coastguard Worker//% case GPBDataType##TYPE: 1351*1b3f573fSAndroid Build Coastguard Worker//% if (fieldType == GPBFieldTypeRepeated) { 1352*1b3f573fSAndroid Build Coastguard Worker//% uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; 1353*1b3f573fSAndroid Build Coastguard Worker//% GPB##ARRAY_TYPE##Array *array = 1354*1b3f573fSAndroid Build Coastguard Worker//% GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1355*1b3f573fSAndroid Build Coastguard Worker//% [output write##TYPE##Array:fieldNumber values:array tag:tag]; 1356*1b3f573fSAndroid Build Coastguard Worker//% } else if (fieldType == GPBFieldTypeSingle) { 1357*1b3f573fSAndroid Build Coastguard Worker//% [output write##TYPE:fieldNumber 1358*1b3f573fSAndroid Build Coastguard Worker//% TYPE$S value:GPBGetMessage##REAL_TYPE##Field(self, field)]; 1359*1b3f573fSAndroid Build Coastguard Worker//% } else { // fieldType == GPBFieldTypeMap 1360*1b3f573fSAndroid Build Coastguard Worker//% // Exact type here doesn't matter. 1361*1b3f573fSAndroid Build Coastguard Worker//% GPBInt32##ARRAY_TYPE##Dictionary *dict = 1362*1b3f573fSAndroid Build Coastguard Worker//% GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1363*1b3f573fSAndroid Build Coastguard Worker//% [dict writeToCodedOutputStream:output asField:field]; 1364*1b3f573fSAndroid Build Coastguard Worker//% } 1365*1b3f573fSAndroid Build Coastguard Worker//% break; 1366*1b3f573fSAndroid Build Coastguard Worker//% 1367*1b3f573fSAndroid Build Coastguard Worker//%PDDM-DEFINE FIELD_CASE2(TYPE) 1368*1b3f573fSAndroid Build Coastguard Worker//% case GPBDataType##TYPE: 1369*1b3f573fSAndroid Build Coastguard Worker//% if (fieldType == GPBFieldTypeRepeated) { 1370*1b3f573fSAndroid Build Coastguard Worker//% NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1371*1b3f573fSAndroid Build Coastguard Worker//% [output write##TYPE##Array:fieldNumber values:array]; 1372*1b3f573fSAndroid Build Coastguard Worker//% } else if (fieldType == GPBFieldTypeSingle) { 1373*1b3f573fSAndroid Build Coastguard Worker//% // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check 1374*1b3f573fSAndroid Build Coastguard Worker//% // again. 1375*1b3f573fSAndroid Build Coastguard Worker//% [output write##TYPE:fieldNumber 1376*1b3f573fSAndroid Build Coastguard Worker//% TYPE$S value:GPBGetObjectIvarWithFieldNoAutocreate(self, field)]; 1377*1b3f573fSAndroid Build Coastguard Worker//% } else { // fieldType == GPBFieldTypeMap 1378*1b3f573fSAndroid Build Coastguard Worker//% // Exact type here doesn't matter. 1379*1b3f573fSAndroid Build Coastguard Worker//% id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1380*1b3f573fSAndroid Build Coastguard Worker//% GPBDataType mapKeyDataType = field.mapKeyDataType; 1381*1b3f573fSAndroid Build Coastguard Worker//% if (mapKeyDataType == GPBDataTypeString) { 1382*1b3f573fSAndroid Build Coastguard Worker//% GPBDictionaryWriteToStreamInternalHelper(output, dict, field); 1383*1b3f573fSAndroid Build Coastguard Worker//% } else { 1384*1b3f573fSAndroid Build Coastguard Worker//% [dict writeToCodedOutputStream:output asField:field]; 1385*1b3f573fSAndroid Build Coastguard Worker//% } 1386*1b3f573fSAndroid Build Coastguard Worker//% } 1387*1b3f573fSAndroid Build Coastguard Worker//% break; 1388*1b3f573fSAndroid Build Coastguard Worker//% 1389*1b3f573fSAndroid Build Coastguard Worker 1390*1b3f573fSAndroid Build Coastguard Worker switch (GPBGetFieldDataType(field)) { 1391*1b3f573fSAndroid Build Coastguard Worker 1392*1b3f573fSAndroid Build Coastguard Worker//%PDDM-EXPAND FIELD_CASE(Bool, Bool) 1393*1b3f573fSAndroid Build Coastguard Worker// This block of code is generated, do not edit it directly. 1394*1b3f573fSAndroid Build Coastguard Worker// clang-format off 1395*1b3f573fSAndroid Build Coastguard Worker 1396*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeBool: 1397*1b3f573fSAndroid Build Coastguard Worker if (fieldType == GPBFieldTypeRepeated) { 1398*1b3f573fSAndroid Build Coastguard Worker uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; 1399*1b3f573fSAndroid Build Coastguard Worker GPBBoolArray *array = 1400*1b3f573fSAndroid Build Coastguard Worker GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1401*1b3f573fSAndroid Build Coastguard Worker [output writeBoolArray:fieldNumber values:array tag:tag]; 1402*1b3f573fSAndroid Build Coastguard Worker } else if (fieldType == GPBFieldTypeSingle) { 1403*1b3f573fSAndroid Build Coastguard Worker [output writeBool:fieldNumber 1404*1b3f573fSAndroid Build Coastguard Worker value:GPBGetMessageBoolField(self, field)]; 1405*1b3f573fSAndroid Build Coastguard Worker } else { // fieldType == GPBFieldTypeMap 1406*1b3f573fSAndroid Build Coastguard Worker // Exact type here doesn't matter. 1407*1b3f573fSAndroid Build Coastguard Worker GPBInt32BoolDictionary *dict = 1408*1b3f573fSAndroid Build Coastguard Worker GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1409*1b3f573fSAndroid Build Coastguard Worker [dict writeToCodedOutputStream:output asField:field]; 1410*1b3f573fSAndroid Build Coastguard Worker } 1411*1b3f573fSAndroid Build Coastguard Worker break; 1412*1b3f573fSAndroid Build Coastguard Worker 1413*1b3f573fSAndroid Build Coastguard Worker// clang-format on 1414*1b3f573fSAndroid Build Coastguard Worker//%PDDM-EXPAND FIELD_CASE(Fixed32, UInt32) 1415*1b3f573fSAndroid Build Coastguard Worker// This block of code is generated, do not edit it directly. 1416*1b3f573fSAndroid Build Coastguard Worker// clang-format off 1417*1b3f573fSAndroid Build Coastguard Worker 1418*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeFixed32: 1419*1b3f573fSAndroid Build Coastguard Worker if (fieldType == GPBFieldTypeRepeated) { 1420*1b3f573fSAndroid Build Coastguard Worker uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; 1421*1b3f573fSAndroid Build Coastguard Worker GPBUInt32Array *array = 1422*1b3f573fSAndroid Build Coastguard Worker GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1423*1b3f573fSAndroid Build Coastguard Worker [output writeFixed32Array:fieldNumber values:array tag:tag]; 1424*1b3f573fSAndroid Build Coastguard Worker } else if (fieldType == GPBFieldTypeSingle) { 1425*1b3f573fSAndroid Build Coastguard Worker [output writeFixed32:fieldNumber 1426*1b3f573fSAndroid Build Coastguard Worker value:GPBGetMessageUInt32Field(self, field)]; 1427*1b3f573fSAndroid Build Coastguard Worker } else { // fieldType == GPBFieldTypeMap 1428*1b3f573fSAndroid Build Coastguard Worker // Exact type here doesn't matter. 1429*1b3f573fSAndroid Build Coastguard Worker GPBInt32UInt32Dictionary *dict = 1430*1b3f573fSAndroid Build Coastguard Worker GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1431*1b3f573fSAndroid Build Coastguard Worker [dict writeToCodedOutputStream:output asField:field]; 1432*1b3f573fSAndroid Build Coastguard Worker } 1433*1b3f573fSAndroid Build Coastguard Worker break; 1434*1b3f573fSAndroid Build Coastguard Worker 1435*1b3f573fSAndroid Build Coastguard Worker// clang-format on 1436*1b3f573fSAndroid Build Coastguard Worker//%PDDM-EXPAND FIELD_CASE(SFixed32, Int32) 1437*1b3f573fSAndroid Build Coastguard Worker// This block of code is generated, do not edit it directly. 1438*1b3f573fSAndroid Build Coastguard Worker// clang-format off 1439*1b3f573fSAndroid Build Coastguard Worker 1440*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeSFixed32: 1441*1b3f573fSAndroid Build Coastguard Worker if (fieldType == GPBFieldTypeRepeated) { 1442*1b3f573fSAndroid Build Coastguard Worker uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; 1443*1b3f573fSAndroid Build Coastguard Worker GPBInt32Array *array = 1444*1b3f573fSAndroid Build Coastguard Worker GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1445*1b3f573fSAndroid Build Coastguard Worker [output writeSFixed32Array:fieldNumber values:array tag:tag]; 1446*1b3f573fSAndroid Build Coastguard Worker } else if (fieldType == GPBFieldTypeSingle) { 1447*1b3f573fSAndroid Build Coastguard Worker [output writeSFixed32:fieldNumber 1448*1b3f573fSAndroid Build Coastguard Worker value:GPBGetMessageInt32Field(self, field)]; 1449*1b3f573fSAndroid Build Coastguard Worker } else { // fieldType == GPBFieldTypeMap 1450*1b3f573fSAndroid Build Coastguard Worker // Exact type here doesn't matter. 1451*1b3f573fSAndroid Build Coastguard Worker GPBInt32Int32Dictionary *dict = 1452*1b3f573fSAndroid Build Coastguard Worker GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1453*1b3f573fSAndroid Build Coastguard Worker [dict writeToCodedOutputStream:output asField:field]; 1454*1b3f573fSAndroid Build Coastguard Worker } 1455*1b3f573fSAndroid Build Coastguard Worker break; 1456*1b3f573fSAndroid Build Coastguard Worker 1457*1b3f573fSAndroid Build Coastguard Worker// clang-format on 1458*1b3f573fSAndroid Build Coastguard Worker//%PDDM-EXPAND FIELD_CASE(Float, Float) 1459*1b3f573fSAndroid Build Coastguard Worker// This block of code is generated, do not edit it directly. 1460*1b3f573fSAndroid Build Coastguard Worker// clang-format off 1461*1b3f573fSAndroid Build Coastguard Worker 1462*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeFloat: 1463*1b3f573fSAndroid Build Coastguard Worker if (fieldType == GPBFieldTypeRepeated) { 1464*1b3f573fSAndroid Build Coastguard Worker uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; 1465*1b3f573fSAndroid Build Coastguard Worker GPBFloatArray *array = 1466*1b3f573fSAndroid Build Coastguard Worker GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1467*1b3f573fSAndroid Build Coastguard Worker [output writeFloatArray:fieldNumber values:array tag:tag]; 1468*1b3f573fSAndroid Build Coastguard Worker } else if (fieldType == GPBFieldTypeSingle) { 1469*1b3f573fSAndroid Build Coastguard Worker [output writeFloat:fieldNumber 1470*1b3f573fSAndroid Build Coastguard Worker value:GPBGetMessageFloatField(self, field)]; 1471*1b3f573fSAndroid Build Coastguard Worker } else { // fieldType == GPBFieldTypeMap 1472*1b3f573fSAndroid Build Coastguard Worker // Exact type here doesn't matter. 1473*1b3f573fSAndroid Build Coastguard Worker GPBInt32FloatDictionary *dict = 1474*1b3f573fSAndroid Build Coastguard Worker GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1475*1b3f573fSAndroid Build Coastguard Worker [dict writeToCodedOutputStream:output asField:field]; 1476*1b3f573fSAndroid Build Coastguard Worker } 1477*1b3f573fSAndroid Build Coastguard Worker break; 1478*1b3f573fSAndroid Build Coastguard Worker 1479*1b3f573fSAndroid Build Coastguard Worker// clang-format on 1480*1b3f573fSAndroid Build Coastguard Worker//%PDDM-EXPAND FIELD_CASE(Fixed64, UInt64) 1481*1b3f573fSAndroid Build Coastguard Worker// This block of code is generated, do not edit it directly. 1482*1b3f573fSAndroid Build Coastguard Worker// clang-format off 1483*1b3f573fSAndroid Build Coastguard Worker 1484*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeFixed64: 1485*1b3f573fSAndroid Build Coastguard Worker if (fieldType == GPBFieldTypeRepeated) { 1486*1b3f573fSAndroid Build Coastguard Worker uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; 1487*1b3f573fSAndroid Build Coastguard Worker GPBUInt64Array *array = 1488*1b3f573fSAndroid Build Coastguard Worker GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1489*1b3f573fSAndroid Build Coastguard Worker [output writeFixed64Array:fieldNumber values:array tag:tag]; 1490*1b3f573fSAndroid Build Coastguard Worker } else if (fieldType == GPBFieldTypeSingle) { 1491*1b3f573fSAndroid Build Coastguard Worker [output writeFixed64:fieldNumber 1492*1b3f573fSAndroid Build Coastguard Worker value:GPBGetMessageUInt64Field(self, field)]; 1493*1b3f573fSAndroid Build Coastguard Worker } else { // fieldType == GPBFieldTypeMap 1494*1b3f573fSAndroid Build Coastguard Worker // Exact type here doesn't matter. 1495*1b3f573fSAndroid Build Coastguard Worker GPBInt32UInt64Dictionary *dict = 1496*1b3f573fSAndroid Build Coastguard Worker GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1497*1b3f573fSAndroid Build Coastguard Worker [dict writeToCodedOutputStream:output asField:field]; 1498*1b3f573fSAndroid Build Coastguard Worker } 1499*1b3f573fSAndroid Build Coastguard Worker break; 1500*1b3f573fSAndroid Build Coastguard Worker 1501*1b3f573fSAndroid Build Coastguard Worker// clang-format on 1502*1b3f573fSAndroid Build Coastguard Worker//%PDDM-EXPAND FIELD_CASE(SFixed64, Int64) 1503*1b3f573fSAndroid Build Coastguard Worker// This block of code is generated, do not edit it directly. 1504*1b3f573fSAndroid Build Coastguard Worker// clang-format off 1505*1b3f573fSAndroid Build Coastguard Worker 1506*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeSFixed64: 1507*1b3f573fSAndroid Build Coastguard Worker if (fieldType == GPBFieldTypeRepeated) { 1508*1b3f573fSAndroid Build Coastguard Worker uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; 1509*1b3f573fSAndroid Build Coastguard Worker GPBInt64Array *array = 1510*1b3f573fSAndroid Build Coastguard Worker GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1511*1b3f573fSAndroid Build Coastguard Worker [output writeSFixed64Array:fieldNumber values:array tag:tag]; 1512*1b3f573fSAndroid Build Coastguard Worker } else if (fieldType == GPBFieldTypeSingle) { 1513*1b3f573fSAndroid Build Coastguard Worker [output writeSFixed64:fieldNumber 1514*1b3f573fSAndroid Build Coastguard Worker value:GPBGetMessageInt64Field(self, field)]; 1515*1b3f573fSAndroid Build Coastguard Worker } else { // fieldType == GPBFieldTypeMap 1516*1b3f573fSAndroid Build Coastguard Worker // Exact type here doesn't matter. 1517*1b3f573fSAndroid Build Coastguard Worker GPBInt32Int64Dictionary *dict = 1518*1b3f573fSAndroid Build Coastguard Worker GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1519*1b3f573fSAndroid Build Coastguard Worker [dict writeToCodedOutputStream:output asField:field]; 1520*1b3f573fSAndroid Build Coastguard Worker } 1521*1b3f573fSAndroid Build Coastguard Worker break; 1522*1b3f573fSAndroid Build Coastguard Worker 1523*1b3f573fSAndroid Build Coastguard Worker// clang-format on 1524*1b3f573fSAndroid Build Coastguard Worker//%PDDM-EXPAND FIELD_CASE(Double, Double) 1525*1b3f573fSAndroid Build Coastguard Worker// This block of code is generated, do not edit it directly. 1526*1b3f573fSAndroid Build Coastguard Worker// clang-format off 1527*1b3f573fSAndroid Build Coastguard Worker 1528*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeDouble: 1529*1b3f573fSAndroid Build Coastguard Worker if (fieldType == GPBFieldTypeRepeated) { 1530*1b3f573fSAndroid Build Coastguard Worker uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; 1531*1b3f573fSAndroid Build Coastguard Worker GPBDoubleArray *array = 1532*1b3f573fSAndroid Build Coastguard Worker GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1533*1b3f573fSAndroid Build Coastguard Worker [output writeDoubleArray:fieldNumber values:array tag:tag]; 1534*1b3f573fSAndroid Build Coastguard Worker } else if (fieldType == GPBFieldTypeSingle) { 1535*1b3f573fSAndroid Build Coastguard Worker [output writeDouble:fieldNumber 1536*1b3f573fSAndroid Build Coastguard Worker value:GPBGetMessageDoubleField(self, field)]; 1537*1b3f573fSAndroid Build Coastguard Worker } else { // fieldType == GPBFieldTypeMap 1538*1b3f573fSAndroid Build Coastguard Worker // Exact type here doesn't matter. 1539*1b3f573fSAndroid Build Coastguard Worker GPBInt32DoubleDictionary *dict = 1540*1b3f573fSAndroid Build Coastguard Worker GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1541*1b3f573fSAndroid Build Coastguard Worker [dict writeToCodedOutputStream:output asField:field]; 1542*1b3f573fSAndroid Build Coastguard Worker } 1543*1b3f573fSAndroid Build Coastguard Worker break; 1544*1b3f573fSAndroid Build Coastguard Worker 1545*1b3f573fSAndroid Build Coastguard Worker// clang-format on 1546*1b3f573fSAndroid Build Coastguard Worker//%PDDM-EXPAND FIELD_CASE(Int32, Int32) 1547*1b3f573fSAndroid Build Coastguard Worker// This block of code is generated, do not edit it directly. 1548*1b3f573fSAndroid Build Coastguard Worker// clang-format off 1549*1b3f573fSAndroid Build Coastguard Worker 1550*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeInt32: 1551*1b3f573fSAndroid Build Coastguard Worker if (fieldType == GPBFieldTypeRepeated) { 1552*1b3f573fSAndroid Build Coastguard Worker uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; 1553*1b3f573fSAndroid Build Coastguard Worker GPBInt32Array *array = 1554*1b3f573fSAndroid Build Coastguard Worker GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1555*1b3f573fSAndroid Build Coastguard Worker [output writeInt32Array:fieldNumber values:array tag:tag]; 1556*1b3f573fSAndroid Build Coastguard Worker } else if (fieldType == GPBFieldTypeSingle) { 1557*1b3f573fSAndroid Build Coastguard Worker [output writeInt32:fieldNumber 1558*1b3f573fSAndroid Build Coastguard Worker value:GPBGetMessageInt32Field(self, field)]; 1559*1b3f573fSAndroid Build Coastguard Worker } else { // fieldType == GPBFieldTypeMap 1560*1b3f573fSAndroid Build Coastguard Worker // Exact type here doesn't matter. 1561*1b3f573fSAndroid Build Coastguard Worker GPBInt32Int32Dictionary *dict = 1562*1b3f573fSAndroid Build Coastguard Worker GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1563*1b3f573fSAndroid Build Coastguard Worker [dict writeToCodedOutputStream:output asField:field]; 1564*1b3f573fSAndroid Build Coastguard Worker } 1565*1b3f573fSAndroid Build Coastguard Worker break; 1566*1b3f573fSAndroid Build Coastguard Worker 1567*1b3f573fSAndroid Build Coastguard Worker// clang-format on 1568*1b3f573fSAndroid Build Coastguard Worker//%PDDM-EXPAND FIELD_CASE(Int64, Int64) 1569*1b3f573fSAndroid Build Coastguard Worker// This block of code is generated, do not edit it directly. 1570*1b3f573fSAndroid Build Coastguard Worker// clang-format off 1571*1b3f573fSAndroid Build Coastguard Worker 1572*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeInt64: 1573*1b3f573fSAndroid Build Coastguard Worker if (fieldType == GPBFieldTypeRepeated) { 1574*1b3f573fSAndroid Build Coastguard Worker uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; 1575*1b3f573fSAndroid Build Coastguard Worker GPBInt64Array *array = 1576*1b3f573fSAndroid Build Coastguard Worker GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1577*1b3f573fSAndroid Build Coastguard Worker [output writeInt64Array:fieldNumber values:array tag:tag]; 1578*1b3f573fSAndroid Build Coastguard Worker } else if (fieldType == GPBFieldTypeSingle) { 1579*1b3f573fSAndroid Build Coastguard Worker [output writeInt64:fieldNumber 1580*1b3f573fSAndroid Build Coastguard Worker value:GPBGetMessageInt64Field(self, field)]; 1581*1b3f573fSAndroid Build Coastguard Worker } else { // fieldType == GPBFieldTypeMap 1582*1b3f573fSAndroid Build Coastguard Worker // Exact type here doesn't matter. 1583*1b3f573fSAndroid Build Coastguard Worker GPBInt32Int64Dictionary *dict = 1584*1b3f573fSAndroid Build Coastguard Worker GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1585*1b3f573fSAndroid Build Coastguard Worker [dict writeToCodedOutputStream:output asField:field]; 1586*1b3f573fSAndroid Build Coastguard Worker } 1587*1b3f573fSAndroid Build Coastguard Worker break; 1588*1b3f573fSAndroid Build Coastguard Worker 1589*1b3f573fSAndroid Build Coastguard Worker// clang-format on 1590*1b3f573fSAndroid Build Coastguard Worker//%PDDM-EXPAND FIELD_CASE(SInt32, Int32) 1591*1b3f573fSAndroid Build Coastguard Worker// This block of code is generated, do not edit it directly. 1592*1b3f573fSAndroid Build Coastguard Worker// clang-format off 1593*1b3f573fSAndroid Build Coastguard Worker 1594*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeSInt32: 1595*1b3f573fSAndroid Build Coastguard Worker if (fieldType == GPBFieldTypeRepeated) { 1596*1b3f573fSAndroid Build Coastguard Worker uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; 1597*1b3f573fSAndroid Build Coastguard Worker GPBInt32Array *array = 1598*1b3f573fSAndroid Build Coastguard Worker GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1599*1b3f573fSAndroid Build Coastguard Worker [output writeSInt32Array:fieldNumber values:array tag:tag]; 1600*1b3f573fSAndroid Build Coastguard Worker } else if (fieldType == GPBFieldTypeSingle) { 1601*1b3f573fSAndroid Build Coastguard Worker [output writeSInt32:fieldNumber 1602*1b3f573fSAndroid Build Coastguard Worker value:GPBGetMessageInt32Field(self, field)]; 1603*1b3f573fSAndroid Build Coastguard Worker } else { // fieldType == GPBFieldTypeMap 1604*1b3f573fSAndroid Build Coastguard Worker // Exact type here doesn't matter. 1605*1b3f573fSAndroid Build Coastguard Worker GPBInt32Int32Dictionary *dict = 1606*1b3f573fSAndroid Build Coastguard Worker GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1607*1b3f573fSAndroid Build Coastguard Worker [dict writeToCodedOutputStream:output asField:field]; 1608*1b3f573fSAndroid Build Coastguard Worker } 1609*1b3f573fSAndroid Build Coastguard Worker break; 1610*1b3f573fSAndroid Build Coastguard Worker 1611*1b3f573fSAndroid Build Coastguard Worker// clang-format on 1612*1b3f573fSAndroid Build Coastguard Worker//%PDDM-EXPAND FIELD_CASE(SInt64, Int64) 1613*1b3f573fSAndroid Build Coastguard Worker// This block of code is generated, do not edit it directly. 1614*1b3f573fSAndroid Build Coastguard Worker// clang-format off 1615*1b3f573fSAndroid Build Coastguard Worker 1616*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeSInt64: 1617*1b3f573fSAndroid Build Coastguard Worker if (fieldType == GPBFieldTypeRepeated) { 1618*1b3f573fSAndroid Build Coastguard Worker uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; 1619*1b3f573fSAndroid Build Coastguard Worker GPBInt64Array *array = 1620*1b3f573fSAndroid Build Coastguard Worker GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1621*1b3f573fSAndroid Build Coastguard Worker [output writeSInt64Array:fieldNumber values:array tag:tag]; 1622*1b3f573fSAndroid Build Coastguard Worker } else if (fieldType == GPBFieldTypeSingle) { 1623*1b3f573fSAndroid Build Coastguard Worker [output writeSInt64:fieldNumber 1624*1b3f573fSAndroid Build Coastguard Worker value:GPBGetMessageInt64Field(self, field)]; 1625*1b3f573fSAndroid Build Coastguard Worker } else { // fieldType == GPBFieldTypeMap 1626*1b3f573fSAndroid Build Coastguard Worker // Exact type here doesn't matter. 1627*1b3f573fSAndroid Build Coastguard Worker GPBInt32Int64Dictionary *dict = 1628*1b3f573fSAndroid Build Coastguard Worker GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1629*1b3f573fSAndroid Build Coastguard Worker [dict writeToCodedOutputStream:output asField:field]; 1630*1b3f573fSAndroid Build Coastguard Worker } 1631*1b3f573fSAndroid Build Coastguard Worker break; 1632*1b3f573fSAndroid Build Coastguard Worker 1633*1b3f573fSAndroid Build Coastguard Worker// clang-format on 1634*1b3f573fSAndroid Build Coastguard Worker//%PDDM-EXPAND FIELD_CASE(UInt32, UInt32) 1635*1b3f573fSAndroid Build Coastguard Worker// This block of code is generated, do not edit it directly. 1636*1b3f573fSAndroid Build Coastguard Worker// clang-format off 1637*1b3f573fSAndroid Build Coastguard Worker 1638*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeUInt32: 1639*1b3f573fSAndroid Build Coastguard Worker if (fieldType == GPBFieldTypeRepeated) { 1640*1b3f573fSAndroid Build Coastguard Worker uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; 1641*1b3f573fSAndroid Build Coastguard Worker GPBUInt32Array *array = 1642*1b3f573fSAndroid Build Coastguard Worker GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1643*1b3f573fSAndroid Build Coastguard Worker [output writeUInt32Array:fieldNumber values:array tag:tag]; 1644*1b3f573fSAndroid Build Coastguard Worker } else if (fieldType == GPBFieldTypeSingle) { 1645*1b3f573fSAndroid Build Coastguard Worker [output writeUInt32:fieldNumber 1646*1b3f573fSAndroid Build Coastguard Worker value:GPBGetMessageUInt32Field(self, field)]; 1647*1b3f573fSAndroid Build Coastguard Worker } else { // fieldType == GPBFieldTypeMap 1648*1b3f573fSAndroid Build Coastguard Worker // Exact type here doesn't matter. 1649*1b3f573fSAndroid Build Coastguard Worker GPBInt32UInt32Dictionary *dict = 1650*1b3f573fSAndroid Build Coastguard Worker GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1651*1b3f573fSAndroid Build Coastguard Worker [dict writeToCodedOutputStream:output asField:field]; 1652*1b3f573fSAndroid Build Coastguard Worker } 1653*1b3f573fSAndroid Build Coastguard Worker break; 1654*1b3f573fSAndroid Build Coastguard Worker 1655*1b3f573fSAndroid Build Coastguard Worker// clang-format on 1656*1b3f573fSAndroid Build Coastguard Worker//%PDDM-EXPAND FIELD_CASE(UInt64, UInt64) 1657*1b3f573fSAndroid Build Coastguard Worker// This block of code is generated, do not edit it directly. 1658*1b3f573fSAndroid Build Coastguard Worker// clang-format off 1659*1b3f573fSAndroid Build Coastguard Worker 1660*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeUInt64: 1661*1b3f573fSAndroid Build Coastguard Worker if (fieldType == GPBFieldTypeRepeated) { 1662*1b3f573fSAndroid Build Coastguard Worker uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; 1663*1b3f573fSAndroid Build Coastguard Worker GPBUInt64Array *array = 1664*1b3f573fSAndroid Build Coastguard Worker GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1665*1b3f573fSAndroid Build Coastguard Worker [output writeUInt64Array:fieldNumber values:array tag:tag]; 1666*1b3f573fSAndroid Build Coastguard Worker } else if (fieldType == GPBFieldTypeSingle) { 1667*1b3f573fSAndroid Build Coastguard Worker [output writeUInt64:fieldNumber 1668*1b3f573fSAndroid Build Coastguard Worker value:GPBGetMessageUInt64Field(self, field)]; 1669*1b3f573fSAndroid Build Coastguard Worker } else { // fieldType == GPBFieldTypeMap 1670*1b3f573fSAndroid Build Coastguard Worker // Exact type here doesn't matter. 1671*1b3f573fSAndroid Build Coastguard Worker GPBInt32UInt64Dictionary *dict = 1672*1b3f573fSAndroid Build Coastguard Worker GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1673*1b3f573fSAndroid Build Coastguard Worker [dict writeToCodedOutputStream:output asField:field]; 1674*1b3f573fSAndroid Build Coastguard Worker } 1675*1b3f573fSAndroid Build Coastguard Worker break; 1676*1b3f573fSAndroid Build Coastguard Worker 1677*1b3f573fSAndroid Build Coastguard Worker// clang-format on 1678*1b3f573fSAndroid Build Coastguard Worker//%PDDM-EXPAND FIELD_CASE_FULL(Enum, Int32, Enum) 1679*1b3f573fSAndroid Build Coastguard Worker// This block of code is generated, do not edit it directly. 1680*1b3f573fSAndroid Build Coastguard Worker// clang-format off 1681*1b3f573fSAndroid Build Coastguard Worker 1682*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeEnum: 1683*1b3f573fSAndroid Build Coastguard Worker if (fieldType == GPBFieldTypeRepeated) { 1684*1b3f573fSAndroid Build Coastguard Worker uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; 1685*1b3f573fSAndroid Build Coastguard Worker GPBEnumArray *array = 1686*1b3f573fSAndroid Build Coastguard Worker GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1687*1b3f573fSAndroid Build Coastguard Worker [output writeEnumArray:fieldNumber values:array tag:tag]; 1688*1b3f573fSAndroid Build Coastguard Worker } else if (fieldType == GPBFieldTypeSingle) { 1689*1b3f573fSAndroid Build Coastguard Worker [output writeEnum:fieldNumber 1690*1b3f573fSAndroid Build Coastguard Worker value:GPBGetMessageInt32Field(self, field)]; 1691*1b3f573fSAndroid Build Coastguard Worker } else { // fieldType == GPBFieldTypeMap 1692*1b3f573fSAndroid Build Coastguard Worker // Exact type here doesn't matter. 1693*1b3f573fSAndroid Build Coastguard Worker GPBInt32EnumDictionary *dict = 1694*1b3f573fSAndroid Build Coastguard Worker GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1695*1b3f573fSAndroid Build Coastguard Worker [dict writeToCodedOutputStream:output asField:field]; 1696*1b3f573fSAndroid Build Coastguard Worker } 1697*1b3f573fSAndroid Build Coastguard Worker break; 1698*1b3f573fSAndroid Build Coastguard Worker 1699*1b3f573fSAndroid Build Coastguard Worker// clang-format on 1700*1b3f573fSAndroid Build Coastguard Worker//%PDDM-EXPAND FIELD_CASE2(Bytes) 1701*1b3f573fSAndroid Build Coastguard Worker// This block of code is generated, do not edit it directly. 1702*1b3f573fSAndroid Build Coastguard Worker// clang-format off 1703*1b3f573fSAndroid Build Coastguard Worker 1704*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeBytes: 1705*1b3f573fSAndroid Build Coastguard Worker if (fieldType == GPBFieldTypeRepeated) { 1706*1b3f573fSAndroid Build Coastguard Worker NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1707*1b3f573fSAndroid Build Coastguard Worker [output writeBytesArray:fieldNumber values:array]; 1708*1b3f573fSAndroid Build Coastguard Worker } else if (fieldType == GPBFieldTypeSingle) { 1709*1b3f573fSAndroid Build Coastguard Worker // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check 1710*1b3f573fSAndroid Build Coastguard Worker // again. 1711*1b3f573fSAndroid Build Coastguard Worker [output writeBytes:fieldNumber 1712*1b3f573fSAndroid Build Coastguard Worker value:GPBGetObjectIvarWithFieldNoAutocreate(self, field)]; 1713*1b3f573fSAndroid Build Coastguard Worker } else { // fieldType == GPBFieldTypeMap 1714*1b3f573fSAndroid Build Coastguard Worker // Exact type here doesn't matter. 1715*1b3f573fSAndroid Build Coastguard Worker id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1716*1b3f573fSAndroid Build Coastguard Worker GPBDataType mapKeyDataType = field.mapKeyDataType; 1717*1b3f573fSAndroid Build Coastguard Worker if (mapKeyDataType == GPBDataTypeString) { 1718*1b3f573fSAndroid Build Coastguard Worker GPBDictionaryWriteToStreamInternalHelper(output, dict, field); 1719*1b3f573fSAndroid Build Coastguard Worker } else { 1720*1b3f573fSAndroid Build Coastguard Worker [dict writeToCodedOutputStream:output asField:field]; 1721*1b3f573fSAndroid Build Coastguard Worker } 1722*1b3f573fSAndroid Build Coastguard Worker } 1723*1b3f573fSAndroid Build Coastguard Worker break; 1724*1b3f573fSAndroid Build Coastguard Worker 1725*1b3f573fSAndroid Build Coastguard Worker// clang-format on 1726*1b3f573fSAndroid Build Coastguard Worker//%PDDM-EXPAND FIELD_CASE2(String) 1727*1b3f573fSAndroid Build Coastguard Worker// This block of code is generated, do not edit it directly. 1728*1b3f573fSAndroid Build Coastguard Worker// clang-format off 1729*1b3f573fSAndroid Build Coastguard Worker 1730*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeString: 1731*1b3f573fSAndroid Build Coastguard Worker if (fieldType == GPBFieldTypeRepeated) { 1732*1b3f573fSAndroid Build Coastguard Worker NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1733*1b3f573fSAndroid Build Coastguard Worker [output writeStringArray:fieldNumber values:array]; 1734*1b3f573fSAndroid Build Coastguard Worker } else if (fieldType == GPBFieldTypeSingle) { 1735*1b3f573fSAndroid Build Coastguard Worker // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check 1736*1b3f573fSAndroid Build Coastguard Worker // again. 1737*1b3f573fSAndroid Build Coastguard Worker [output writeString:fieldNumber 1738*1b3f573fSAndroid Build Coastguard Worker value:GPBGetObjectIvarWithFieldNoAutocreate(self, field)]; 1739*1b3f573fSAndroid Build Coastguard Worker } else { // fieldType == GPBFieldTypeMap 1740*1b3f573fSAndroid Build Coastguard Worker // Exact type here doesn't matter. 1741*1b3f573fSAndroid Build Coastguard Worker id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1742*1b3f573fSAndroid Build Coastguard Worker GPBDataType mapKeyDataType = field.mapKeyDataType; 1743*1b3f573fSAndroid Build Coastguard Worker if (mapKeyDataType == GPBDataTypeString) { 1744*1b3f573fSAndroid Build Coastguard Worker GPBDictionaryWriteToStreamInternalHelper(output, dict, field); 1745*1b3f573fSAndroid Build Coastguard Worker } else { 1746*1b3f573fSAndroid Build Coastguard Worker [dict writeToCodedOutputStream:output asField:field]; 1747*1b3f573fSAndroid Build Coastguard Worker } 1748*1b3f573fSAndroid Build Coastguard Worker } 1749*1b3f573fSAndroid Build Coastguard Worker break; 1750*1b3f573fSAndroid Build Coastguard Worker 1751*1b3f573fSAndroid Build Coastguard Worker// clang-format on 1752*1b3f573fSAndroid Build Coastguard Worker//%PDDM-EXPAND FIELD_CASE2(Message) 1753*1b3f573fSAndroid Build Coastguard Worker// This block of code is generated, do not edit it directly. 1754*1b3f573fSAndroid Build Coastguard Worker// clang-format off 1755*1b3f573fSAndroid Build Coastguard Worker 1756*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeMessage: 1757*1b3f573fSAndroid Build Coastguard Worker if (fieldType == GPBFieldTypeRepeated) { 1758*1b3f573fSAndroid Build Coastguard Worker NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1759*1b3f573fSAndroid Build Coastguard Worker [output writeMessageArray:fieldNumber values:array]; 1760*1b3f573fSAndroid Build Coastguard Worker } else if (fieldType == GPBFieldTypeSingle) { 1761*1b3f573fSAndroid Build Coastguard Worker // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check 1762*1b3f573fSAndroid Build Coastguard Worker // again. 1763*1b3f573fSAndroid Build Coastguard Worker [output writeMessage:fieldNumber 1764*1b3f573fSAndroid Build Coastguard Worker value:GPBGetObjectIvarWithFieldNoAutocreate(self, field)]; 1765*1b3f573fSAndroid Build Coastguard Worker } else { // fieldType == GPBFieldTypeMap 1766*1b3f573fSAndroid Build Coastguard Worker // Exact type here doesn't matter. 1767*1b3f573fSAndroid Build Coastguard Worker id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1768*1b3f573fSAndroid Build Coastguard Worker GPBDataType mapKeyDataType = field.mapKeyDataType; 1769*1b3f573fSAndroid Build Coastguard Worker if (mapKeyDataType == GPBDataTypeString) { 1770*1b3f573fSAndroid Build Coastguard Worker GPBDictionaryWriteToStreamInternalHelper(output, dict, field); 1771*1b3f573fSAndroid Build Coastguard Worker } else { 1772*1b3f573fSAndroid Build Coastguard Worker [dict writeToCodedOutputStream:output asField:field]; 1773*1b3f573fSAndroid Build Coastguard Worker } 1774*1b3f573fSAndroid Build Coastguard Worker } 1775*1b3f573fSAndroid Build Coastguard Worker break; 1776*1b3f573fSAndroid Build Coastguard Worker 1777*1b3f573fSAndroid Build Coastguard Worker// clang-format on 1778*1b3f573fSAndroid Build Coastguard Worker//%PDDM-EXPAND FIELD_CASE2(Group) 1779*1b3f573fSAndroid Build Coastguard Worker// This block of code is generated, do not edit it directly. 1780*1b3f573fSAndroid Build Coastguard Worker// clang-format off 1781*1b3f573fSAndroid Build Coastguard Worker 1782*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeGroup: 1783*1b3f573fSAndroid Build Coastguard Worker if (fieldType == GPBFieldTypeRepeated) { 1784*1b3f573fSAndroid Build Coastguard Worker NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1785*1b3f573fSAndroid Build Coastguard Worker [output writeGroupArray:fieldNumber values:array]; 1786*1b3f573fSAndroid Build Coastguard Worker } else if (fieldType == GPBFieldTypeSingle) { 1787*1b3f573fSAndroid Build Coastguard Worker // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check 1788*1b3f573fSAndroid Build Coastguard Worker // again. 1789*1b3f573fSAndroid Build Coastguard Worker [output writeGroup:fieldNumber 1790*1b3f573fSAndroid Build Coastguard Worker value:GPBGetObjectIvarWithFieldNoAutocreate(self, field)]; 1791*1b3f573fSAndroid Build Coastguard Worker } else { // fieldType == GPBFieldTypeMap 1792*1b3f573fSAndroid Build Coastguard Worker // Exact type here doesn't matter. 1793*1b3f573fSAndroid Build Coastguard Worker id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); 1794*1b3f573fSAndroid Build Coastguard Worker GPBDataType mapKeyDataType = field.mapKeyDataType; 1795*1b3f573fSAndroid Build Coastguard Worker if (mapKeyDataType == GPBDataTypeString) { 1796*1b3f573fSAndroid Build Coastguard Worker GPBDictionaryWriteToStreamInternalHelper(output, dict, field); 1797*1b3f573fSAndroid Build Coastguard Worker } else { 1798*1b3f573fSAndroid Build Coastguard Worker [dict writeToCodedOutputStream:output asField:field]; 1799*1b3f573fSAndroid Build Coastguard Worker } 1800*1b3f573fSAndroid Build Coastguard Worker } 1801*1b3f573fSAndroid Build Coastguard Worker break; 1802*1b3f573fSAndroid Build Coastguard Worker 1803*1b3f573fSAndroid Build Coastguard Worker// clang-format on 1804*1b3f573fSAndroid Build Coastguard Worker//%PDDM-EXPAND-END (18 expansions) 1805*1b3f573fSAndroid Build Coastguard Worker } 1806*1b3f573fSAndroid Build Coastguard Worker} 1807*1b3f573fSAndroid Build Coastguard Worker 1808*1b3f573fSAndroid Build Coastguard Worker#pragma mark - Extensions 1809*1b3f573fSAndroid Build Coastguard Worker 1810*1b3f573fSAndroid Build Coastguard Worker- (id)getExtension:(GPBExtensionDescriptor *)extension { 1811*1b3f573fSAndroid Build Coastguard Worker CheckExtension(self, extension); 1812*1b3f573fSAndroid Build Coastguard Worker id value = [extensionMap_ objectForKey:extension]; 1813*1b3f573fSAndroid Build Coastguard Worker if (value != nil) { 1814*1b3f573fSAndroid Build Coastguard Worker return value; 1815*1b3f573fSAndroid Build Coastguard Worker } 1816*1b3f573fSAndroid Build Coastguard Worker 1817*1b3f573fSAndroid Build Coastguard Worker // No default for repeated. 1818*1b3f573fSAndroid Build Coastguard Worker if (extension.isRepeated) { 1819*1b3f573fSAndroid Build Coastguard Worker return nil; 1820*1b3f573fSAndroid Build Coastguard Worker } 1821*1b3f573fSAndroid Build Coastguard Worker // Non messages get their default. 1822*1b3f573fSAndroid Build Coastguard Worker if (!GPBExtensionIsMessage(extension)) { 1823*1b3f573fSAndroid Build Coastguard Worker return extension.defaultValue; 1824*1b3f573fSAndroid Build Coastguard Worker } 1825*1b3f573fSAndroid Build Coastguard Worker 1826*1b3f573fSAndroid Build Coastguard Worker // Check for an autocreated value. 1827*1b3f573fSAndroid Build Coastguard Worker GPBPrepareReadOnlySemaphore(self); 1828*1b3f573fSAndroid Build Coastguard Worker dispatch_semaphore_wait(readOnlySemaphore_, DISPATCH_TIME_FOREVER); 1829*1b3f573fSAndroid Build Coastguard Worker value = [autocreatedExtensionMap_ objectForKey:extension]; 1830*1b3f573fSAndroid Build Coastguard Worker if (!value) { 1831*1b3f573fSAndroid Build Coastguard Worker // Auto create the message extensions to match normal fields. 1832*1b3f573fSAndroid Build Coastguard Worker value = CreateMessageWithAutocreatorForExtension(extension.msgClass, self, 1833*1b3f573fSAndroid Build Coastguard Worker extension); 1834*1b3f573fSAndroid Build Coastguard Worker 1835*1b3f573fSAndroid Build Coastguard Worker if (autocreatedExtensionMap_ == nil) { 1836*1b3f573fSAndroid Build Coastguard Worker autocreatedExtensionMap_ = [[NSMutableDictionary alloc] init]; 1837*1b3f573fSAndroid Build Coastguard Worker } 1838*1b3f573fSAndroid Build Coastguard Worker 1839*1b3f573fSAndroid Build Coastguard Worker // We can't simply call setExtension here because that would clear the new 1840*1b3f573fSAndroid Build Coastguard Worker // value's autocreator. 1841*1b3f573fSAndroid Build Coastguard Worker [autocreatedExtensionMap_ setObject:value forKey:extension]; 1842*1b3f573fSAndroid Build Coastguard Worker [value release]; 1843*1b3f573fSAndroid Build Coastguard Worker } 1844*1b3f573fSAndroid Build Coastguard Worker 1845*1b3f573fSAndroid Build Coastguard Worker dispatch_semaphore_signal(readOnlySemaphore_); 1846*1b3f573fSAndroid Build Coastguard Worker return value; 1847*1b3f573fSAndroid Build Coastguard Worker} 1848*1b3f573fSAndroid Build Coastguard Worker 1849*1b3f573fSAndroid Build Coastguard Worker- (id)getExistingExtension:(GPBExtensionDescriptor *)extension { 1850*1b3f573fSAndroid Build Coastguard Worker // This is an internal method so we don't need to call CheckExtension(). 1851*1b3f573fSAndroid Build Coastguard Worker return [extensionMap_ objectForKey:extension]; 1852*1b3f573fSAndroid Build Coastguard Worker} 1853*1b3f573fSAndroid Build Coastguard Worker 1854*1b3f573fSAndroid Build Coastguard Worker- (BOOL)hasExtension:(GPBExtensionDescriptor *)extension { 1855*1b3f573fSAndroid Build Coastguard Worker#if defined(DEBUG) && DEBUG 1856*1b3f573fSAndroid Build Coastguard Worker CheckExtension(self, extension); 1857*1b3f573fSAndroid Build Coastguard Worker#endif // DEBUG 1858*1b3f573fSAndroid Build Coastguard Worker return nil != [extensionMap_ objectForKey:extension]; 1859*1b3f573fSAndroid Build Coastguard Worker} 1860*1b3f573fSAndroid Build Coastguard Worker 1861*1b3f573fSAndroid Build Coastguard Worker- (NSArray *)extensionsCurrentlySet { 1862*1b3f573fSAndroid Build Coastguard Worker return [extensionMap_ allKeys]; 1863*1b3f573fSAndroid Build Coastguard Worker} 1864*1b3f573fSAndroid Build Coastguard Worker 1865*1b3f573fSAndroid Build Coastguard Worker- (void)writeExtensionsToCodedOutputStream:(GPBCodedOutputStream *)output 1866*1b3f573fSAndroid Build Coastguard Worker range:(GPBExtensionRange)range 1867*1b3f573fSAndroid Build Coastguard Worker sortedExtensions:(NSArray *)sortedExtensions { 1868*1b3f573fSAndroid Build Coastguard Worker uint32_t start = range.start; 1869*1b3f573fSAndroid Build Coastguard Worker uint32_t end = range.end; 1870*1b3f573fSAndroid Build Coastguard Worker for (GPBExtensionDescriptor *extension in sortedExtensions) { 1871*1b3f573fSAndroid Build Coastguard Worker uint32_t fieldNumber = extension.fieldNumber; 1872*1b3f573fSAndroid Build Coastguard Worker if (fieldNumber < start) { 1873*1b3f573fSAndroid Build Coastguard Worker continue; 1874*1b3f573fSAndroid Build Coastguard Worker } 1875*1b3f573fSAndroid Build Coastguard Worker if (fieldNumber >= end) { 1876*1b3f573fSAndroid Build Coastguard Worker break; 1877*1b3f573fSAndroid Build Coastguard Worker } 1878*1b3f573fSAndroid Build Coastguard Worker id value = [extensionMap_ objectForKey:extension]; 1879*1b3f573fSAndroid Build Coastguard Worker GPBWriteExtensionValueToOutputStream(extension, value, output); 1880*1b3f573fSAndroid Build Coastguard Worker } 1881*1b3f573fSAndroid Build Coastguard Worker} 1882*1b3f573fSAndroid Build Coastguard Worker 1883*1b3f573fSAndroid Build Coastguard Worker- (void)setExtension:(GPBExtensionDescriptor *)extension value:(id)value { 1884*1b3f573fSAndroid Build Coastguard Worker if (!value) { 1885*1b3f573fSAndroid Build Coastguard Worker [self clearExtension:extension]; 1886*1b3f573fSAndroid Build Coastguard Worker return; 1887*1b3f573fSAndroid Build Coastguard Worker } 1888*1b3f573fSAndroid Build Coastguard Worker 1889*1b3f573fSAndroid Build Coastguard Worker CheckExtension(self, extension); 1890*1b3f573fSAndroid Build Coastguard Worker 1891*1b3f573fSAndroid Build Coastguard Worker if (extension.repeated) { 1892*1b3f573fSAndroid Build Coastguard Worker [NSException raise:NSInvalidArgumentException 1893*1b3f573fSAndroid Build Coastguard Worker format:@"Must call addExtension() for repeated types."]; 1894*1b3f573fSAndroid Build Coastguard Worker } 1895*1b3f573fSAndroid Build Coastguard Worker 1896*1b3f573fSAndroid Build Coastguard Worker if (extensionMap_ == nil) { 1897*1b3f573fSAndroid Build Coastguard Worker extensionMap_ = [[NSMutableDictionary alloc] init]; 1898*1b3f573fSAndroid Build Coastguard Worker } 1899*1b3f573fSAndroid Build Coastguard Worker 1900*1b3f573fSAndroid Build Coastguard Worker // This pointless cast is for CLANG_WARN_NULLABLE_TO_NONNULL_CONVERSION. 1901*1b3f573fSAndroid Build Coastguard Worker // Without it, the compiler complains we're passing an id nullable when 1902*1b3f573fSAndroid Build Coastguard Worker // setObject:forKey: requires a id nonnull for the value. The check for 1903*1b3f573fSAndroid Build Coastguard Worker // !value at the start of the method ensures it isn't nil, but the check 1904*1b3f573fSAndroid Build Coastguard Worker // isn't smart enough to realize that. 1905*1b3f573fSAndroid Build Coastguard Worker [extensionMap_ setObject:(id)value forKey:extension]; 1906*1b3f573fSAndroid Build Coastguard Worker 1907*1b3f573fSAndroid Build Coastguard Worker GPBExtensionDescriptor *descriptor = extension; 1908*1b3f573fSAndroid Build Coastguard Worker 1909*1b3f573fSAndroid Build Coastguard Worker if (GPBExtensionIsMessage(descriptor) && !descriptor.isRepeated) { 1910*1b3f573fSAndroid Build Coastguard Worker GPBMessage *autocreatedValue = 1911*1b3f573fSAndroid Build Coastguard Worker [[autocreatedExtensionMap_ objectForKey:extension] retain]; 1912*1b3f573fSAndroid Build Coastguard Worker // Must remove from the map before calling GPBClearMessageAutocreator() so 1913*1b3f573fSAndroid Build Coastguard Worker // that GPBClearMessageAutocreator() knows its safe to clear. 1914*1b3f573fSAndroid Build Coastguard Worker [autocreatedExtensionMap_ removeObjectForKey:extension]; 1915*1b3f573fSAndroid Build Coastguard Worker GPBClearMessageAutocreator(autocreatedValue); 1916*1b3f573fSAndroid Build Coastguard Worker [autocreatedValue release]; 1917*1b3f573fSAndroid Build Coastguard Worker } 1918*1b3f573fSAndroid Build Coastguard Worker 1919*1b3f573fSAndroid Build Coastguard Worker GPBBecomeVisibleToAutocreator(self); 1920*1b3f573fSAndroid Build Coastguard Worker} 1921*1b3f573fSAndroid Build Coastguard Worker 1922*1b3f573fSAndroid Build Coastguard Worker- (void)addExtension:(GPBExtensionDescriptor *)extension value:(id)value { 1923*1b3f573fSAndroid Build Coastguard Worker CheckExtension(self, extension); 1924*1b3f573fSAndroid Build Coastguard Worker 1925*1b3f573fSAndroid Build Coastguard Worker if (!extension.repeated) { 1926*1b3f573fSAndroid Build Coastguard Worker [NSException raise:NSInvalidArgumentException 1927*1b3f573fSAndroid Build Coastguard Worker format:@"Must call setExtension() for singular types."]; 1928*1b3f573fSAndroid Build Coastguard Worker } 1929*1b3f573fSAndroid Build Coastguard Worker 1930*1b3f573fSAndroid Build Coastguard Worker if (extensionMap_ == nil) { 1931*1b3f573fSAndroid Build Coastguard Worker extensionMap_ = [[NSMutableDictionary alloc] init]; 1932*1b3f573fSAndroid Build Coastguard Worker } 1933*1b3f573fSAndroid Build Coastguard Worker NSMutableArray *list = [extensionMap_ objectForKey:extension]; 1934*1b3f573fSAndroid Build Coastguard Worker if (list == nil) { 1935*1b3f573fSAndroid Build Coastguard Worker list = [NSMutableArray array]; 1936*1b3f573fSAndroid Build Coastguard Worker [extensionMap_ setObject:list forKey:extension]; 1937*1b3f573fSAndroid Build Coastguard Worker } 1938*1b3f573fSAndroid Build Coastguard Worker 1939*1b3f573fSAndroid Build Coastguard Worker [list addObject:value]; 1940*1b3f573fSAndroid Build Coastguard Worker GPBBecomeVisibleToAutocreator(self); 1941*1b3f573fSAndroid Build Coastguard Worker} 1942*1b3f573fSAndroid Build Coastguard Worker 1943*1b3f573fSAndroid Build Coastguard Worker- (void)setExtension:(GPBExtensionDescriptor *)extension 1944*1b3f573fSAndroid Build Coastguard Worker index:(NSUInteger)idx 1945*1b3f573fSAndroid Build Coastguard Worker value:(id)value { 1946*1b3f573fSAndroid Build Coastguard Worker CheckExtension(self, extension); 1947*1b3f573fSAndroid Build Coastguard Worker 1948*1b3f573fSAndroid Build Coastguard Worker if (!extension.repeated) { 1949*1b3f573fSAndroid Build Coastguard Worker [NSException raise:NSInvalidArgumentException 1950*1b3f573fSAndroid Build Coastguard Worker format:@"Must call setExtension() for singular types."]; 1951*1b3f573fSAndroid Build Coastguard Worker } 1952*1b3f573fSAndroid Build Coastguard Worker 1953*1b3f573fSAndroid Build Coastguard Worker if (extensionMap_ == nil) { 1954*1b3f573fSAndroid Build Coastguard Worker extensionMap_ = [[NSMutableDictionary alloc] init]; 1955*1b3f573fSAndroid Build Coastguard Worker } 1956*1b3f573fSAndroid Build Coastguard Worker 1957*1b3f573fSAndroid Build Coastguard Worker NSMutableArray *list = [extensionMap_ objectForKey:extension]; 1958*1b3f573fSAndroid Build Coastguard Worker 1959*1b3f573fSAndroid Build Coastguard Worker [list replaceObjectAtIndex:idx withObject:value]; 1960*1b3f573fSAndroid Build Coastguard Worker GPBBecomeVisibleToAutocreator(self); 1961*1b3f573fSAndroid Build Coastguard Worker} 1962*1b3f573fSAndroid Build Coastguard Worker 1963*1b3f573fSAndroid Build Coastguard Worker- (void)clearExtension:(GPBExtensionDescriptor *)extension { 1964*1b3f573fSAndroid Build Coastguard Worker CheckExtension(self, extension); 1965*1b3f573fSAndroid Build Coastguard Worker 1966*1b3f573fSAndroid Build Coastguard Worker // Only become visible if there was actually a value to clear. 1967*1b3f573fSAndroid Build Coastguard Worker if ([extensionMap_ objectForKey:extension]) { 1968*1b3f573fSAndroid Build Coastguard Worker [extensionMap_ removeObjectForKey:extension]; 1969*1b3f573fSAndroid Build Coastguard Worker GPBBecomeVisibleToAutocreator(self); 1970*1b3f573fSAndroid Build Coastguard Worker } 1971*1b3f573fSAndroid Build Coastguard Worker} 1972*1b3f573fSAndroid Build Coastguard Worker 1973*1b3f573fSAndroid Build Coastguard Worker#pragma mark - mergeFrom 1974*1b3f573fSAndroid Build Coastguard Worker 1975*1b3f573fSAndroid Build Coastguard Worker- (void)mergeFromData:(NSData *)data 1976*1b3f573fSAndroid Build Coastguard Worker extensionRegistry:(GPBExtensionRegistry *)extensionRegistry { 1977*1b3f573fSAndroid Build Coastguard Worker GPBCodedInputStream *input = [[GPBCodedInputStream alloc] initWithData:data]; 1978*1b3f573fSAndroid Build Coastguard Worker [self mergeFromCodedInputStream:input extensionRegistry:extensionRegistry]; 1979*1b3f573fSAndroid Build Coastguard Worker [input checkLastTagWas:0]; 1980*1b3f573fSAndroid Build Coastguard Worker [input release]; 1981*1b3f573fSAndroid Build Coastguard Worker} 1982*1b3f573fSAndroid Build Coastguard Worker 1983*1b3f573fSAndroid Build Coastguard Worker#pragma mark - mergeDelimitedFrom 1984*1b3f573fSAndroid Build Coastguard Worker 1985*1b3f573fSAndroid Build Coastguard Worker- (void)mergeDelimitedFromCodedInputStream:(GPBCodedInputStream *)input 1986*1b3f573fSAndroid Build Coastguard Worker extensionRegistry:(GPBExtensionRegistry *)extensionRegistry { 1987*1b3f573fSAndroid Build Coastguard Worker GPBCodedInputStreamState *state = &input->state_; 1988*1b3f573fSAndroid Build Coastguard Worker if (GPBCodedInputStreamIsAtEnd(state)) { 1989*1b3f573fSAndroid Build Coastguard Worker return; 1990*1b3f573fSAndroid Build Coastguard Worker } 1991*1b3f573fSAndroid Build Coastguard Worker NSData *data = GPBCodedInputStreamReadRetainedBytesNoCopy(state); 1992*1b3f573fSAndroid Build Coastguard Worker if (data == nil) { 1993*1b3f573fSAndroid Build Coastguard Worker return; 1994*1b3f573fSAndroid Build Coastguard Worker } 1995*1b3f573fSAndroid Build Coastguard Worker [self mergeFromData:data extensionRegistry:extensionRegistry]; 1996*1b3f573fSAndroid Build Coastguard Worker [data release]; 1997*1b3f573fSAndroid Build Coastguard Worker} 1998*1b3f573fSAndroid Build Coastguard Worker 1999*1b3f573fSAndroid Build Coastguard Worker#pragma mark - Parse From Data Support 2000*1b3f573fSAndroid Build Coastguard Worker 2001*1b3f573fSAndroid Build Coastguard Worker+ (instancetype)parseFromData:(NSData *)data error:(NSError **)errorPtr { 2002*1b3f573fSAndroid Build Coastguard Worker return [self parseFromData:data extensionRegistry:nil error:errorPtr]; 2003*1b3f573fSAndroid Build Coastguard Worker} 2004*1b3f573fSAndroid Build Coastguard Worker 2005*1b3f573fSAndroid Build Coastguard Worker+ (instancetype)parseFromData:(NSData *)data 2006*1b3f573fSAndroid Build Coastguard Worker extensionRegistry:(GPBExtensionRegistry *)extensionRegistry 2007*1b3f573fSAndroid Build Coastguard Worker error:(NSError **)errorPtr { 2008*1b3f573fSAndroid Build Coastguard Worker return [[[self alloc] initWithData:data 2009*1b3f573fSAndroid Build Coastguard Worker extensionRegistry:extensionRegistry 2010*1b3f573fSAndroid Build Coastguard Worker error:errorPtr] autorelease]; 2011*1b3f573fSAndroid Build Coastguard Worker} 2012*1b3f573fSAndroid Build Coastguard Worker 2013*1b3f573fSAndroid Build Coastguard Worker+ (instancetype)parseFromCodedInputStream:(GPBCodedInputStream *)input 2014*1b3f573fSAndroid Build Coastguard Worker extensionRegistry:(GPBExtensionRegistry *)extensionRegistry 2015*1b3f573fSAndroid Build Coastguard Worker error:(NSError **)errorPtr { 2016*1b3f573fSAndroid Build Coastguard Worker return 2017*1b3f573fSAndroid Build Coastguard Worker [[[self alloc] initWithCodedInputStream:input 2018*1b3f573fSAndroid Build Coastguard Worker extensionRegistry:extensionRegistry 2019*1b3f573fSAndroid Build Coastguard Worker error:errorPtr] autorelease]; 2020*1b3f573fSAndroid Build Coastguard Worker} 2021*1b3f573fSAndroid Build Coastguard Worker 2022*1b3f573fSAndroid Build Coastguard Worker#pragma mark - Parse Delimited From Data Support 2023*1b3f573fSAndroid Build Coastguard Worker 2024*1b3f573fSAndroid Build Coastguard Worker+ (instancetype)parseDelimitedFromCodedInputStream:(GPBCodedInputStream *)input 2025*1b3f573fSAndroid Build Coastguard Worker extensionRegistry: 2026*1b3f573fSAndroid Build Coastguard Worker (GPBExtensionRegistry *)extensionRegistry 2027*1b3f573fSAndroid Build Coastguard Worker error:(NSError **)errorPtr { 2028*1b3f573fSAndroid Build Coastguard Worker GPBMessage *message = [[[self alloc] init] autorelease]; 2029*1b3f573fSAndroid Build Coastguard Worker @try { 2030*1b3f573fSAndroid Build Coastguard Worker [message mergeDelimitedFromCodedInputStream:input 2031*1b3f573fSAndroid Build Coastguard Worker extensionRegistry:extensionRegistry]; 2032*1b3f573fSAndroid Build Coastguard Worker if (errorPtr) { 2033*1b3f573fSAndroid Build Coastguard Worker *errorPtr = nil; 2034*1b3f573fSAndroid Build Coastguard Worker } 2035*1b3f573fSAndroid Build Coastguard Worker } 2036*1b3f573fSAndroid Build Coastguard Worker @catch (NSException *exception) { 2037*1b3f573fSAndroid Build Coastguard Worker message = nil; 2038*1b3f573fSAndroid Build Coastguard Worker if (errorPtr) { 2039*1b3f573fSAndroid Build Coastguard Worker *errorPtr = ErrorFromException(exception); 2040*1b3f573fSAndroid Build Coastguard Worker } 2041*1b3f573fSAndroid Build Coastguard Worker } 2042*1b3f573fSAndroid Build Coastguard Worker#ifdef DEBUG 2043*1b3f573fSAndroid Build Coastguard Worker if (message && !message.initialized) { 2044*1b3f573fSAndroid Build Coastguard Worker message = nil; 2045*1b3f573fSAndroid Build Coastguard Worker if (errorPtr) { 2046*1b3f573fSAndroid Build Coastguard Worker *errorPtr = MessageError(GPBMessageErrorCodeMissingRequiredField, nil); 2047*1b3f573fSAndroid Build Coastguard Worker } 2048*1b3f573fSAndroid Build Coastguard Worker } 2049*1b3f573fSAndroid Build Coastguard Worker#endif 2050*1b3f573fSAndroid Build Coastguard Worker return message; 2051*1b3f573fSAndroid Build Coastguard Worker} 2052*1b3f573fSAndroid Build Coastguard Worker 2053*1b3f573fSAndroid Build Coastguard Worker#pragma mark - Unknown Field Support 2054*1b3f573fSAndroid Build Coastguard Worker 2055*1b3f573fSAndroid Build Coastguard Worker- (GPBUnknownFieldSet *)unknownFields { 2056*1b3f573fSAndroid Build Coastguard Worker return unknownFields_; 2057*1b3f573fSAndroid Build Coastguard Worker} 2058*1b3f573fSAndroid Build Coastguard Worker 2059*1b3f573fSAndroid Build Coastguard Worker- (void)setUnknownFields:(GPBUnknownFieldSet *)unknownFields { 2060*1b3f573fSAndroid Build Coastguard Worker if (unknownFields != unknownFields_) { 2061*1b3f573fSAndroid Build Coastguard Worker [unknownFields_ release]; 2062*1b3f573fSAndroid Build Coastguard Worker unknownFields_ = [unknownFields copy]; 2063*1b3f573fSAndroid Build Coastguard Worker GPBBecomeVisibleToAutocreator(self); 2064*1b3f573fSAndroid Build Coastguard Worker } 2065*1b3f573fSAndroid Build Coastguard Worker} 2066*1b3f573fSAndroid Build Coastguard Worker 2067*1b3f573fSAndroid Build Coastguard Worker- (void)parseMessageSet:(GPBCodedInputStream *)input 2068*1b3f573fSAndroid Build Coastguard Worker extensionRegistry:(GPBExtensionRegistry *)extensionRegistry { 2069*1b3f573fSAndroid Build Coastguard Worker uint32_t typeId = 0; 2070*1b3f573fSAndroid Build Coastguard Worker NSData *rawBytes = nil; 2071*1b3f573fSAndroid Build Coastguard Worker GPBExtensionDescriptor *extension = nil; 2072*1b3f573fSAndroid Build Coastguard Worker GPBCodedInputStreamState *state = &input->state_; 2073*1b3f573fSAndroid Build Coastguard Worker while (true) { 2074*1b3f573fSAndroid Build Coastguard Worker uint32_t tag = GPBCodedInputStreamReadTag(state); 2075*1b3f573fSAndroid Build Coastguard Worker if (tag == 0) { 2076*1b3f573fSAndroid Build Coastguard Worker break; 2077*1b3f573fSAndroid Build Coastguard Worker } 2078*1b3f573fSAndroid Build Coastguard Worker 2079*1b3f573fSAndroid Build Coastguard Worker if (tag == GPBWireFormatMessageSetTypeIdTag) { 2080*1b3f573fSAndroid Build Coastguard Worker typeId = GPBCodedInputStreamReadUInt32(state); 2081*1b3f573fSAndroid Build Coastguard Worker if (typeId != 0) { 2082*1b3f573fSAndroid Build Coastguard Worker extension = [extensionRegistry extensionForDescriptor:[self descriptor] 2083*1b3f573fSAndroid Build Coastguard Worker fieldNumber:typeId]; 2084*1b3f573fSAndroid Build Coastguard Worker } 2085*1b3f573fSAndroid Build Coastguard Worker } else if (tag == GPBWireFormatMessageSetMessageTag) { 2086*1b3f573fSAndroid Build Coastguard Worker rawBytes = 2087*1b3f573fSAndroid Build Coastguard Worker [GPBCodedInputStreamReadRetainedBytesNoCopy(state) autorelease]; 2088*1b3f573fSAndroid Build Coastguard Worker } else { 2089*1b3f573fSAndroid Build Coastguard Worker if (![input skipField:tag]) { 2090*1b3f573fSAndroid Build Coastguard Worker break; 2091*1b3f573fSAndroid Build Coastguard Worker } 2092*1b3f573fSAndroid Build Coastguard Worker } 2093*1b3f573fSAndroid Build Coastguard Worker } 2094*1b3f573fSAndroid Build Coastguard Worker 2095*1b3f573fSAndroid Build Coastguard Worker [input checkLastTagWas:GPBWireFormatMessageSetItemEndTag]; 2096*1b3f573fSAndroid Build Coastguard Worker 2097*1b3f573fSAndroid Build Coastguard Worker if (rawBytes != nil && typeId != 0) { 2098*1b3f573fSAndroid Build Coastguard Worker if (extension != nil) { 2099*1b3f573fSAndroid Build Coastguard Worker GPBCodedInputStream *newInput = 2100*1b3f573fSAndroid Build Coastguard Worker [[GPBCodedInputStream alloc] initWithData:rawBytes]; 2101*1b3f573fSAndroid Build Coastguard Worker GPBExtensionMergeFromInputStream(extension, 2102*1b3f573fSAndroid Build Coastguard Worker extension.packable, 2103*1b3f573fSAndroid Build Coastguard Worker newInput, 2104*1b3f573fSAndroid Build Coastguard Worker extensionRegistry, 2105*1b3f573fSAndroid Build Coastguard Worker self); 2106*1b3f573fSAndroid Build Coastguard Worker [newInput release]; 2107*1b3f573fSAndroid Build Coastguard Worker } else { 2108*1b3f573fSAndroid Build Coastguard Worker GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self); 2109*1b3f573fSAndroid Build Coastguard Worker // rawBytes was created via a NoCopy, so it can be reusing a 2110*1b3f573fSAndroid Build Coastguard Worker // subrange of another NSData that might go out of scope as things 2111*1b3f573fSAndroid Build Coastguard Worker // unwind, so a copy is needed to ensure what is saved in the 2112*1b3f573fSAndroid Build Coastguard Worker // unknown fields stays valid. 2113*1b3f573fSAndroid Build Coastguard Worker NSData *cloned = [NSData dataWithData:rawBytes]; 2114*1b3f573fSAndroid Build Coastguard Worker [unknownFields mergeMessageSetMessage:typeId data:cloned]; 2115*1b3f573fSAndroid Build Coastguard Worker } 2116*1b3f573fSAndroid Build Coastguard Worker } 2117*1b3f573fSAndroid Build Coastguard Worker} 2118*1b3f573fSAndroid Build Coastguard Worker 2119*1b3f573fSAndroid Build Coastguard Worker- (BOOL)parseUnknownField:(GPBCodedInputStream *)input 2120*1b3f573fSAndroid Build Coastguard Worker extensionRegistry:(GPBExtensionRegistry *)extensionRegistry 2121*1b3f573fSAndroid Build Coastguard Worker tag:(uint32_t)tag { 2122*1b3f573fSAndroid Build Coastguard Worker GPBWireFormat wireType = GPBWireFormatGetTagWireType(tag); 2123*1b3f573fSAndroid Build Coastguard Worker int32_t fieldNumber = GPBWireFormatGetTagFieldNumber(tag); 2124*1b3f573fSAndroid Build Coastguard Worker 2125*1b3f573fSAndroid Build Coastguard Worker GPBDescriptor *descriptor = [self descriptor]; 2126*1b3f573fSAndroid Build Coastguard Worker GPBExtensionDescriptor *extension = 2127*1b3f573fSAndroid Build Coastguard Worker [extensionRegistry extensionForDescriptor:descriptor 2128*1b3f573fSAndroid Build Coastguard Worker fieldNumber:fieldNumber]; 2129*1b3f573fSAndroid Build Coastguard Worker if (extension == nil) { 2130*1b3f573fSAndroid Build Coastguard Worker if (descriptor.wireFormat && GPBWireFormatMessageSetItemTag == tag) { 2131*1b3f573fSAndroid Build Coastguard Worker [self parseMessageSet:input extensionRegistry:extensionRegistry]; 2132*1b3f573fSAndroid Build Coastguard Worker return YES; 2133*1b3f573fSAndroid Build Coastguard Worker } 2134*1b3f573fSAndroid Build Coastguard Worker } else { 2135*1b3f573fSAndroid Build Coastguard Worker if (extension.wireType == wireType) { 2136*1b3f573fSAndroid Build Coastguard Worker GPBExtensionMergeFromInputStream(extension, 2137*1b3f573fSAndroid Build Coastguard Worker extension.packable, 2138*1b3f573fSAndroid Build Coastguard Worker input, 2139*1b3f573fSAndroid Build Coastguard Worker extensionRegistry, 2140*1b3f573fSAndroid Build Coastguard Worker self); 2141*1b3f573fSAndroid Build Coastguard Worker return YES; 2142*1b3f573fSAndroid Build Coastguard Worker } 2143*1b3f573fSAndroid Build Coastguard Worker // Primitive, repeated types can be packed on unpacked on the wire, and are 2144*1b3f573fSAndroid Build Coastguard Worker // parsed either way. 2145*1b3f573fSAndroid Build Coastguard Worker if ([extension isRepeated] && 2146*1b3f573fSAndroid Build Coastguard Worker !GPBDataTypeIsObject(extension->description_->dataType) && 2147*1b3f573fSAndroid Build Coastguard Worker (extension.alternateWireType == wireType)) { 2148*1b3f573fSAndroid Build Coastguard Worker GPBExtensionMergeFromInputStream(extension, 2149*1b3f573fSAndroid Build Coastguard Worker !extension.packable, 2150*1b3f573fSAndroid Build Coastguard Worker input, 2151*1b3f573fSAndroid Build Coastguard Worker extensionRegistry, 2152*1b3f573fSAndroid Build Coastguard Worker self); 2153*1b3f573fSAndroid Build Coastguard Worker return YES; 2154*1b3f573fSAndroid Build Coastguard Worker } 2155*1b3f573fSAndroid Build Coastguard Worker } 2156*1b3f573fSAndroid Build Coastguard Worker if ([GPBUnknownFieldSet isFieldTag:tag]) { 2157*1b3f573fSAndroid Build Coastguard Worker GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self); 2158*1b3f573fSAndroid Build Coastguard Worker return [unknownFields mergeFieldFrom:tag input:input]; 2159*1b3f573fSAndroid Build Coastguard Worker } else { 2160*1b3f573fSAndroid Build Coastguard Worker return NO; 2161*1b3f573fSAndroid Build Coastguard Worker } 2162*1b3f573fSAndroid Build Coastguard Worker} 2163*1b3f573fSAndroid Build Coastguard Worker 2164*1b3f573fSAndroid Build Coastguard Worker- (void)addUnknownMapEntry:(int32_t)fieldNum value:(NSData *)data { 2165*1b3f573fSAndroid Build Coastguard Worker GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self); 2166*1b3f573fSAndroid Build Coastguard Worker [unknownFields addUnknownMapEntry:fieldNum value:data]; 2167*1b3f573fSAndroid Build Coastguard Worker} 2168*1b3f573fSAndroid Build Coastguard Worker 2169*1b3f573fSAndroid Build Coastguard Worker#pragma mark - MergeFromCodedInputStream Support 2170*1b3f573fSAndroid Build Coastguard Worker 2171*1b3f573fSAndroid Build Coastguard Workerstatic void MergeSingleFieldFromCodedInputStream( 2172*1b3f573fSAndroid Build Coastguard Worker GPBMessage *self, GPBFieldDescriptor *field, GPBFileSyntax syntax, 2173*1b3f573fSAndroid Build Coastguard Worker GPBCodedInputStream *input, GPBExtensionRegistry *extensionRegistry) { 2174*1b3f573fSAndroid Build Coastguard Worker GPBDataType fieldDataType = GPBGetFieldDataType(field); 2175*1b3f573fSAndroid Build Coastguard Worker switch (fieldDataType) { 2176*1b3f573fSAndroid Build Coastguard Worker#define CASE_SINGLE_POD(NAME, TYPE, FUNC_TYPE) \ 2177*1b3f573fSAndroid Build Coastguard Worker case GPBDataType##NAME: { \ 2178*1b3f573fSAndroid Build Coastguard Worker TYPE val = GPBCodedInputStreamRead##NAME(&input->state_); \ 2179*1b3f573fSAndroid Build Coastguard Worker GPBSet##FUNC_TYPE##IvarWithFieldPrivate(self, field, val); \ 2180*1b3f573fSAndroid Build Coastguard Worker break; \ 2181*1b3f573fSAndroid Build Coastguard Worker } 2182*1b3f573fSAndroid Build Coastguard Worker#define CASE_SINGLE_OBJECT(NAME) \ 2183*1b3f573fSAndroid Build Coastguard Worker case GPBDataType##NAME: { \ 2184*1b3f573fSAndroid Build Coastguard Worker id val = GPBCodedInputStreamReadRetained##NAME(&input->state_); \ 2185*1b3f573fSAndroid Build Coastguard Worker GPBSetRetainedObjectIvarWithFieldPrivate(self, field, val); \ 2186*1b3f573fSAndroid Build Coastguard Worker break; \ 2187*1b3f573fSAndroid Build Coastguard Worker } 2188*1b3f573fSAndroid Build Coastguard Worker CASE_SINGLE_POD(Bool, BOOL, Bool) 2189*1b3f573fSAndroid Build Coastguard Worker CASE_SINGLE_POD(Fixed32, uint32_t, UInt32) 2190*1b3f573fSAndroid Build Coastguard Worker CASE_SINGLE_POD(SFixed32, int32_t, Int32) 2191*1b3f573fSAndroid Build Coastguard Worker CASE_SINGLE_POD(Float, float, Float) 2192*1b3f573fSAndroid Build Coastguard Worker CASE_SINGLE_POD(Fixed64, uint64_t, UInt64) 2193*1b3f573fSAndroid Build Coastguard Worker CASE_SINGLE_POD(SFixed64, int64_t, Int64) 2194*1b3f573fSAndroid Build Coastguard Worker CASE_SINGLE_POD(Double, double, Double) 2195*1b3f573fSAndroid Build Coastguard Worker CASE_SINGLE_POD(Int32, int32_t, Int32) 2196*1b3f573fSAndroid Build Coastguard Worker CASE_SINGLE_POD(Int64, int64_t, Int64) 2197*1b3f573fSAndroid Build Coastguard Worker CASE_SINGLE_POD(SInt32, int32_t, Int32) 2198*1b3f573fSAndroid Build Coastguard Worker CASE_SINGLE_POD(SInt64, int64_t, Int64) 2199*1b3f573fSAndroid Build Coastguard Worker CASE_SINGLE_POD(UInt32, uint32_t, UInt32) 2200*1b3f573fSAndroid Build Coastguard Worker CASE_SINGLE_POD(UInt64, uint64_t, UInt64) 2201*1b3f573fSAndroid Build Coastguard Worker CASE_SINGLE_OBJECT(Bytes) 2202*1b3f573fSAndroid Build Coastguard Worker CASE_SINGLE_OBJECT(String) 2203*1b3f573fSAndroid Build Coastguard Worker#undef CASE_SINGLE_POD 2204*1b3f573fSAndroid Build Coastguard Worker#undef CASE_SINGLE_OBJECT 2205*1b3f573fSAndroid Build Coastguard Worker 2206*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeMessage: { 2207*1b3f573fSAndroid Build Coastguard Worker if (GPBGetHasIvarField(self, field)) { 2208*1b3f573fSAndroid Build Coastguard Worker // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has 2209*1b3f573fSAndroid Build Coastguard Worker // check again. 2210*1b3f573fSAndroid Build Coastguard Worker GPBMessage *message = 2211*1b3f573fSAndroid Build Coastguard Worker GPBGetObjectIvarWithFieldNoAutocreate(self, field); 2212*1b3f573fSAndroid Build Coastguard Worker [input readMessage:message extensionRegistry:extensionRegistry]; 2213*1b3f573fSAndroid Build Coastguard Worker } else { 2214*1b3f573fSAndroid Build Coastguard Worker GPBMessage *message = [[field.msgClass alloc] init]; 2215*1b3f573fSAndroid Build Coastguard Worker [input readMessage:message extensionRegistry:extensionRegistry]; 2216*1b3f573fSAndroid Build Coastguard Worker GPBSetRetainedObjectIvarWithFieldPrivate(self, field, message); 2217*1b3f573fSAndroid Build Coastguard Worker } 2218*1b3f573fSAndroid Build Coastguard Worker break; 2219*1b3f573fSAndroid Build Coastguard Worker } 2220*1b3f573fSAndroid Build Coastguard Worker 2221*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeGroup: { 2222*1b3f573fSAndroid Build Coastguard Worker if (GPBGetHasIvarField(self, field)) { 2223*1b3f573fSAndroid Build Coastguard Worker // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has 2224*1b3f573fSAndroid Build Coastguard Worker // check again. 2225*1b3f573fSAndroid Build Coastguard Worker GPBMessage *message = 2226*1b3f573fSAndroid Build Coastguard Worker GPBGetObjectIvarWithFieldNoAutocreate(self, field); 2227*1b3f573fSAndroid Build Coastguard Worker [input readGroup:GPBFieldNumber(field) 2228*1b3f573fSAndroid Build Coastguard Worker message:message 2229*1b3f573fSAndroid Build Coastguard Worker extensionRegistry:extensionRegistry]; 2230*1b3f573fSAndroid Build Coastguard Worker } else { 2231*1b3f573fSAndroid Build Coastguard Worker GPBMessage *message = [[field.msgClass alloc] init]; 2232*1b3f573fSAndroid Build Coastguard Worker [input readGroup:GPBFieldNumber(field) 2233*1b3f573fSAndroid Build Coastguard Worker message:message 2234*1b3f573fSAndroid Build Coastguard Worker extensionRegistry:extensionRegistry]; 2235*1b3f573fSAndroid Build Coastguard Worker GPBSetRetainedObjectIvarWithFieldPrivate(self, field, message); 2236*1b3f573fSAndroid Build Coastguard Worker } 2237*1b3f573fSAndroid Build Coastguard Worker break; 2238*1b3f573fSAndroid Build Coastguard Worker } 2239*1b3f573fSAndroid Build Coastguard Worker 2240*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeEnum: { 2241*1b3f573fSAndroid Build Coastguard Worker int32_t val = GPBCodedInputStreamReadEnum(&input->state_); 2242*1b3f573fSAndroid Build Coastguard Worker if (GPBHasPreservingUnknownEnumSemantics(syntax) || 2243*1b3f573fSAndroid Build Coastguard Worker [field isValidEnumValue:val]) { 2244*1b3f573fSAndroid Build Coastguard Worker GPBSetInt32IvarWithFieldPrivate(self, field, val); 2245*1b3f573fSAndroid Build Coastguard Worker } else { 2246*1b3f573fSAndroid Build Coastguard Worker GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self); 2247*1b3f573fSAndroid Build Coastguard Worker [unknownFields mergeVarintField:GPBFieldNumber(field) value:val]; 2248*1b3f573fSAndroid Build Coastguard Worker } 2249*1b3f573fSAndroid Build Coastguard Worker } 2250*1b3f573fSAndroid Build Coastguard Worker } // switch 2251*1b3f573fSAndroid Build Coastguard Worker} 2252*1b3f573fSAndroid Build Coastguard Worker 2253*1b3f573fSAndroid Build Coastguard Workerstatic void MergeRepeatedPackedFieldFromCodedInputStream( 2254*1b3f573fSAndroid Build Coastguard Worker GPBMessage *self, GPBFieldDescriptor *field, GPBFileSyntax syntax, 2255*1b3f573fSAndroid Build Coastguard Worker GPBCodedInputStream *input) { 2256*1b3f573fSAndroid Build Coastguard Worker GPBDataType fieldDataType = GPBGetFieldDataType(field); 2257*1b3f573fSAndroid Build Coastguard Worker GPBCodedInputStreamState *state = &input->state_; 2258*1b3f573fSAndroid Build Coastguard Worker id genericArray = GetOrCreateArrayIvarWithField(self, field); 2259*1b3f573fSAndroid Build Coastguard Worker int32_t length = GPBCodedInputStreamReadInt32(state); 2260*1b3f573fSAndroid Build Coastguard Worker size_t limit = GPBCodedInputStreamPushLimit(state, length); 2261*1b3f573fSAndroid Build Coastguard Worker while (GPBCodedInputStreamBytesUntilLimit(state) > 0) { 2262*1b3f573fSAndroid Build Coastguard Worker switch (fieldDataType) { 2263*1b3f573fSAndroid Build Coastguard Worker#define CASE_REPEATED_PACKED_POD(NAME, TYPE, ARRAY_TYPE) \ 2264*1b3f573fSAndroid Build Coastguard Worker case GPBDataType##NAME: { \ 2265*1b3f573fSAndroid Build Coastguard Worker TYPE val = GPBCodedInputStreamRead##NAME(state); \ 2266*1b3f573fSAndroid Build Coastguard Worker [(GPB##ARRAY_TYPE##Array *)genericArray addValue:val]; \ 2267*1b3f573fSAndroid Build Coastguard Worker break; \ 2268*1b3f573fSAndroid Build Coastguard Worker } 2269*1b3f573fSAndroid Build Coastguard Worker CASE_REPEATED_PACKED_POD(Bool, BOOL, Bool) 2270*1b3f573fSAndroid Build Coastguard Worker CASE_REPEATED_PACKED_POD(Fixed32, uint32_t, UInt32) 2271*1b3f573fSAndroid Build Coastguard Worker CASE_REPEATED_PACKED_POD(SFixed32, int32_t, Int32) 2272*1b3f573fSAndroid Build Coastguard Worker CASE_REPEATED_PACKED_POD(Float, float, Float) 2273*1b3f573fSAndroid Build Coastguard Worker CASE_REPEATED_PACKED_POD(Fixed64, uint64_t, UInt64) 2274*1b3f573fSAndroid Build Coastguard Worker CASE_REPEATED_PACKED_POD(SFixed64, int64_t, Int64) 2275*1b3f573fSAndroid Build Coastguard Worker CASE_REPEATED_PACKED_POD(Double, double, Double) 2276*1b3f573fSAndroid Build Coastguard Worker CASE_REPEATED_PACKED_POD(Int32, int32_t, Int32) 2277*1b3f573fSAndroid Build Coastguard Worker CASE_REPEATED_PACKED_POD(Int64, int64_t, Int64) 2278*1b3f573fSAndroid Build Coastguard Worker CASE_REPEATED_PACKED_POD(SInt32, int32_t, Int32) 2279*1b3f573fSAndroid Build Coastguard Worker CASE_REPEATED_PACKED_POD(SInt64, int64_t, Int64) 2280*1b3f573fSAndroid Build Coastguard Worker CASE_REPEATED_PACKED_POD(UInt32, uint32_t, UInt32) 2281*1b3f573fSAndroid Build Coastguard Worker CASE_REPEATED_PACKED_POD(UInt64, uint64_t, UInt64) 2282*1b3f573fSAndroid Build Coastguard Worker#undef CASE_REPEATED_PACKED_POD 2283*1b3f573fSAndroid Build Coastguard Worker 2284*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeBytes: 2285*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeString: 2286*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeMessage: 2287*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeGroup: 2288*1b3f573fSAndroid Build Coastguard Worker NSCAssert(NO, @"Non primitive types can't be packed"); 2289*1b3f573fSAndroid Build Coastguard Worker break; 2290*1b3f573fSAndroid Build Coastguard Worker 2291*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeEnum: { 2292*1b3f573fSAndroid Build Coastguard Worker int32_t val = GPBCodedInputStreamReadEnum(state); 2293*1b3f573fSAndroid Build Coastguard Worker if (GPBHasPreservingUnknownEnumSemantics(syntax) || 2294*1b3f573fSAndroid Build Coastguard Worker [field isValidEnumValue:val]) { 2295*1b3f573fSAndroid Build Coastguard Worker [(GPBEnumArray*)genericArray addRawValue:val]; 2296*1b3f573fSAndroid Build Coastguard Worker } else { 2297*1b3f573fSAndroid Build Coastguard Worker GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self); 2298*1b3f573fSAndroid Build Coastguard Worker [unknownFields mergeVarintField:GPBFieldNumber(field) value:val]; 2299*1b3f573fSAndroid Build Coastguard Worker } 2300*1b3f573fSAndroid Build Coastguard Worker break; 2301*1b3f573fSAndroid Build Coastguard Worker } 2302*1b3f573fSAndroid Build Coastguard Worker } // switch 2303*1b3f573fSAndroid Build Coastguard Worker } // while(BytesUntilLimit() > 0) 2304*1b3f573fSAndroid Build Coastguard Worker GPBCodedInputStreamPopLimit(state, limit); 2305*1b3f573fSAndroid Build Coastguard Worker} 2306*1b3f573fSAndroid Build Coastguard Worker 2307*1b3f573fSAndroid Build Coastguard Workerstatic void MergeRepeatedNotPackedFieldFromCodedInputStream( 2308*1b3f573fSAndroid Build Coastguard Worker GPBMessage *self, GPBFieldDescriptor *field, GPBFileSyntax syntax, 2309*1b3f573fSAndroid Build Coastguard Worker GPBCodedInputStream *input, GPBExtensionRegistry *extensionRegistry) { 2310*1b3f573fSAndroid Build Coastguard Worker GPBCodedInputStreamState *state = &input->state_; 2311*1b3f573fSAndroid Build Coastguard Worker id genericArray = GetOrCreateArrayIvarWithField(self, field); 2312*1b3f573fSAndroid Build Coastguard Worker switch (GPBGetFieldDataType(field)) { 2313*1b3f573fSAndroid Build Coastguard Worker#define CASE_REPEATED_NOT_PACKED_POD(NAME, TYPE, ARRAY_TYPE) \ 2314*1b3f573fSAndroid Build Coastguard Worker case GPBDataType##NAME: { \ 2315*1b3f573fSAndroid Build Coastguard Worker TYPE val = GPBCodedInputStreamRead##NAME(state); \ 2316*1b3f573fSAndroid Build Coastguard Worker [(GPB##ARRAY_TYPE##Array *)genericArray addValue:val]; \ 2317*1b3f573fSAndroid Build Coastguard Worker break; \ 2318*1b3f573fSAndroid Build Coastguard Worker } 2319*1b3f573fSAndroid Build Coastguard Worker#define CASE_REPEATED_NOT_PACKED_OBJECT(NAME) \ 2320*1b3f573fSAndroid Build Coastguard Worker case GPBDataType##NAME: { \ 2321*1b3f573fSAndroid Build Coastguard Worker id val = GPBCodedInputStreamReadRetained##NAME(state); \ 2322*1b3f573fSAndroid Build Coastguard Worker [(NSMutableArray*)genericArray addObject:val]; \ 2323*1b3f573fSAndroid Build Coastguard Worker [val release]; \ 2324*1b3f573fSAndroid Build Coastguard Worker break; \ 2325*1b3f573fSAndroid Build Coastguard Worker } 2326*1b3f573fSAndroid Build Coastguard Worker CASE_REPEATED_NOT_PACKED_POD(Bool, BOOL, Bool) 2327*1b3f573fSAndroid Build Coastguard Worker CASE_REPEATED_NOT_PACKED_POD(Fixed32, uint32_t, UInt32) 2328*1b3f573fSAndroid Build Coastguard Worker CASE_REPEATED_NOT_PACKED_POD(SFixed32, int32_t, Int32) 2329*1b3f573fSAndroid Build Coastguard Worker CASE_REPEATED_NOT_PACKED_POD(Float, float, Float) 2330*1b3f573fSAndroid Build Coastguard Worker CASE_REPEATED_NOT_PACKED_POD(Fixed64, uint64_t, UInt64) 2331*1b3f573fSAndroid Build Coastguard Worker CASE_REPEATED_NOT_PACKED_POD(SFixed64, int64_t, Int64) 2332*1b3f573fSAndroid Build Coastguard Worker CASE_REPEATED_NOT_PACKED_POD(Double, double, Double) 2333*1b3f573fSAndroid Build Coastguard Worker CASE_REPEATED_NOT_PACKED_POD(Int32, int32_t, Int32) 2334*1b3f573fSAndroid Build Coastguard Worker CASE_REPEATED_NOT_PACKED_POD(Int64, int64_t, Int64) 2335*1b3f573fSAndroid Build Coastguard Worker CASE_REPEATED_NOT_PACKED_POD(SInt32, int32_t, Int32) 2336*1b3f573fSAndroid Build Coastguard Worker CASE_REPEATED_NOT_PACKED_POD(SInt64, int64_t, Int64) 2337*1b3f573fSAndroid Build Coastguard Worker CASE_REPEATED_NOT_PACKED_POD(UInt32, uint32_t, UInt32) 2338*1b3f573fSAndroid Build Coastguard Worker CASE_REPEATED_NOT_PACKED_POD(UInt64, uint64_t, UInt64) 2339*1b3f573fSAndroid Build Coastguard Worker CASE_REPEATED_NOT_PACKED_OBJECT(Bytes) 2340*1b3f573fSAndroid Build Coastguard Worker CASE_REPEATED_NOT_PACKED_OBJECT(String) 2341*1b3f573fSAndroid Build Coastguard Worker#undef CASE_REPEATED_NOT_PACKED_POD 2342*1b3f573fSAndroid Build Coastguard Worker#undef CASE_NOT_PACKED_OBJECT 2343*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeMessage: { 2344*1b3f573fSAndroid Build Coastguard Worker GPBMessage *message = [[field.msgClass alloc] init]; 2345*1b3f573fSAndroid Build Coastguard Worker [input readMessage:message extensionRegistry:extensionRegistry]; 2346*1b3f573fSAndroid Build Coastguard Worker [(NSMutableArray*)genericArray addObject:message]; 2347*1b3f573fSAndroid Build Coastguard Worker [message release]; 2348*1b3f573fSAndroid Build Coastguard Worker break; 2349*1b3f573fSAndroid Build Coastguard Worker } 2350*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeGroup: { 2351*1b3f573fSAndroid Build Coastguard Worker GPBMessage *message = [[field.msgClass alloc] init]; 2352*1b3f573fSAndroid Build Coastguard Worker [input readGroup:GPBFieldNumber(field) 2353*1b3f573fSAndroid Build Coastguard Worker message:message 2354*1b3f573fSAndroid Build Coastguard Worker extensionRegistry:extensionRegistry]; 2355*1b3f573fSAndroid Build Coastguard Worker [(NSMutableArray*)genericArray addObject:message]; 2356*1b3f573fSAndroid Build Coastguard Worker [message release]; 2357*1b3f573fSAndroid Build Coastguard Worker break; 2358*1b3f573fSAndroid Build Coastguard Worker } 2359*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeEnum: { 2360*1b3f573fSAndroid Build Coastguard Worker int32_t val = GPBCodedInputStreamReadEnum(state); 2361*1b3f573fSAndroid Build Coastguard Worker if (GPBHasPreservingUnknownEnumSemantics(syntax) || 2362*1b3f573fSAndroid Build Coastguard Worker [field isValidEnumValue:val]) { 2363*1b3f573fSAndroid Build Coastguard Worker [(GPBEnumArray*)genericArray addRawValue:val]; 2364*1b3f573fSAndroid Build Coastguard Worker } else { 2365*1b3f573fSAndroid Build Coastguard Worker GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self); 2366*1b3f573fSAndroid Build Coastguard Worker [unknownFields mergeVarintField:GPBFieldNumber(field) value:val]; 2367*1b3f573fSAndroid Build Coastguard Worker } 2368*1b3f573fSAndroid Build Coastguard Worker break; 2369*1b3f573fSAndroid Build Coastguard Worker } 2370*1b3f573fSAndroid Build Coastguard Worker } // switch 2371*1b3f573fSAndroid Build Coastguard Worker} 2372*1b3f573fSAndroid Build Coastguard Worker 2373*1b3f573fSAndroid Build Coastguard Worker- (void)mergeFromCodedInputStream:(GPBCodedInputStream *)input 2374*1b3f573fSAndroid Build Coastguard Worker extensionRegistry:(GPBExtensionRegistry *)extensionRegistry { 2375*1b3f573fSAndroid Build Coastguard Worker GPBDescriptor *descriptor = [self descriptor]; 2376*1b3f573fSAndroid Build Coastguard Worker GPBFileSyntax syntax = descriptor.file.syntax; 2377*1b3f573fSAndroid Build Coastguard Worker GPBCodedInputStreamState *state = &input->state_; 2378*1b3f573fSAndroid Build Coastguard Worker uint32_t tag = 0; 2379*1b3f573fSAndroid Build Coastguard Worker NSUInteger startingIndex = 0; 2380*1b3f573fSAndroid Build Coastguard Worker NSArray *fields = descriptor->fields_; 2381*1b3f573fSAndroid Build Coastguard Worker NSUInteger numFields = fields.count; 2382*1b3f573fSAndroid Build Coastguard Worker while (YES) { 2383*1b3f573fSAndroid Build Coastguard Worker BOOL merged = NO; 2384*1b3f573fSAndroid Build Coastguard Worker tag = GPBCodedInputStreamReadTag(state); 2385*1b3f573fSAndroid Build Coastguard Worker if (tag == 0) { 2386*1b3f573fSAndroid Build Coastguard Worker break; // Reached end. 2387*1b3f573fSAndroid Build Coastguard Worker } 2388*1b3f573fSAndroid Build Coastguard Worker for (NSUInteger i = 0; i < numFields; ++i) { 2389*1b3f573fSAndroid Build Coastguard Worker if (startingIndex >= numFields) startingIndex = 0; 2390*1b3f573fSAndroid Build Coastguard Worker GPBFieldDescriptor *fieldDescriptor = fields[startingIndex]; 2391*1b3f573fSAndroid Build Coastguard Worker if (GPBFieldTag(fieldDescriptor) == tag) { 2392*1b3f573fSAndroid Build Coastguard Worker GPBFieldType fieldType = fieldDescriptor.fieldType; 2393*1b3f573fSAndroid Build Coastguard Worker if (fieldType == GPBFieldTypeSingle) { 2394*1b3f573fSAndroid Build Coastguard Worker MergeSingleFieldFromCodedInputStream(self, fieldDescriptor, syntax, 2395*1b3f573fSAndroid Build Coastguard Worker input, extensionRegistry); 2396*1b3f573fSAndroid Build Coastguard Worker // Well formed protos will only have a single field once, advance 2397*1b3f573fSAndroid Build Coastguard Worker // the starting index to the next field. 2398*1b3f573fSAndroid Build Coastguard Worker startingIndex += 1; 2399*1b3f573fSAndroid Build Coastguard Worker } else if (fieldType == GPBFieldTypeRepeated) { 2400*1b3f573fSAndroid Build Coastguard Worker if (fieldDescriptor.isPackable) { 2401*1b3f573fSAndroid Build Coastguard Worker MergeRepeatedPackedFieldFromCodedInputStream( 2402*1b3f573fSAndroid Build Coastguard Worker self, fieldDescriptor, syntax, input); 2403*1b3f573fSAndroid Build Coastguard Worker // Well formed protos will only have a repeated field that is 2404*1b3f573fSAndroid Build Coastguard Worker // packed once, advance the starting index to the next field. 2405*1b3f573fSAndroid Build Coastguard Worker startingIndex += 1; 2406*1b3f573fSAndroid Build Coastguard Worker } else { 2407*1b3f573fSAndroid Build Coastguard Worker MergeRepeatedNotPackedFieldFromCodedInputStream( 2408*1b3f573fSAndroid Build Coastguard Worker self, fieldDescriptor, syntax, input, extensionRegistry); 2409*1b3f573fSAndroid Build Coastguard Worker } 2410*1b3f573fSAndroid Build Coastguard Worker } else { // fieldType == GPBFieldTypeMap 2411*1b3f573fSAndroid Build Coastguard Worker // GPB*Dictionary or NSDictionary, exact type doesn't matter at this 2412*1b3f573fSAndroid Build Coastguard Worker // point. 2413*1b3f573fSAndroid Build Coastguard Worker id map = GetOrCreateMapIvarWithField(self, fieldDescriptor); 2414*1b3f573fSAndroid Build Coastguard Worker [input readMapEntry:map 2415*1b3f573fSAndroid Build Coastguard Worker extensionRegistry:extensionRegistry 2416*1b3f573fSAndroid Build Coastguard Worker field:fieldDescriptor 2417*1b3f573fSAndroid Build Coastguard Worker parentMessage:self]; 2418*1b3f573fSAndroid Build Coastguard Worker } 2419*1b3f573fSAndroid Build Coastguard Worker merged = YES; 2420*1b3f573fSAndroid Build Coastguard Worker break; 2421*1b3f573fSAndroid Build Coastguard Worker } else { 2422*1b3f573fSAndroid Build Coastguard Worker startingIndex += 1; 2423*1b3f573fSAndroid Build Coastguard Worker } 2424*1b3f573fSAndroid Build Coastguard Worker } // for(i < numFields) 2425*1b3f573fSAndroid Build Coastguard Worker 2426*1b3f573fSAndroid Build Coastguard Worker if (!merged && (tag != 0)) { 2427*1b3f573fSAndroid Build Coastguard Worker // Primitive, repeated types can be packed on unpacked on the wire, and 2428*1b3f573fSAndroid Build Coastguard Worker // are parsed either way. The above loop covered tag in the preferred 2429*1b3f573fSAndroid Build Coastguard Worker // for, so this need to check the alternate form. 2430*1b3f573fSAndroid Build Coastguard Worker for (NSUInteger i = 0; i < numFields; ++i) { 2431*1b3f573fSAndroid Build Coastguard Worker if (startingIndex >= numFields) startingIndex = 0; 2432*1b3f573fSAndroid Build Coastguard Worker GPBFieldDescriptor *fieldDescriptor = fields[startingIndex]; 2433*1b3f573fSAndroid Build Coastguard Worker if ((fieldDescriptor.fieldType == GPBFieldTypeRepeated) && 2434*1b3f573fSAndroid Build Coastguard Worker !GPBFieldDataTypeIsObject(fieldDescriptor) && 2435*1b3f573fSAndroid Build Coastguard Worker (GPBFieldAlternateTag(fieldDescriptor) == tag)) { 2436*1b3f573fSAndroid Build Coastguard Worker BOOL alternateIsPacked = !fieldDescriptor.isPackable; 2437*1b3f573fSAndroid Build Coastguard Worker if (alternateIsPacked) { 2438*1b3f573fSAndroid Build Coastguard Worker MergeRepeatedPackedFieldFromCodedInputStream( 2439*1b3f573fSAndroid Build Coastguard Worker self, fieldDescriptor, syntax, input); 2440*1b3f573fSAndroid Build Coastguard Worker // Well formed protos will only have a repeated field that is 2441*1b3f573fSAndroid Build Coastguard Worker // packed once, advance the starting index to the next field. 2442*1b3f573fSAndroid Build Coastguard Worker startingIndex += 1; 2443*1b3f573fSAndroid Build Coastguard Worker } else { 2444*1b3f573fSAndroid Build Coastguard Worker MergeRepeatedNotPackedFieldFromCodedInputStream( 2445*1b3f573fSAndroid Build Coastguard Worker self, fieldDescriptor, syntax, input, extensionRegistry); 2446*1b3f573fSAndroid Build Coastguard Worker } 2447*1b3f573fSAndroid Build Coastguard Worker merged = YES; 2448*1b3f573fSAndroid Build Coastguard Worker break; 2449*1b3f573fSAndroid Build Coastguard Worker } else { 2450*1b3f573fSAndroid Build Coastguard Worker startingIndex += 1; 2451*1b3f573fSAndroid Build Coastguard Worker } 2452*1b3f573fSAndroid Build Coastguard Worker } 2453*1b3f573fSAndroid Build Coastguard Worker } 2454*1b3f573fSAndroid Build Coastguard Worker 2455*1b3f573fSAndroid Build Coastguard Worker if (!merged) { 2456*1b3f573fSAndroid Build Coastguard Worker if (tag == 0) { 2457*1b3f573fSAndroid Build Coastguard Worker // zero signals EOF / limit reached 2458*1b3f573fSAndroid Build Coastguard Worker return; 2459*1b3f573fSAndroid Build Coastguard Worker } else { 2460*1b3f573fSAndroid Build Coastguard Worker if (![self parseUnknownField:input 2461*1b3f573fSAndroid Build Coastguard Worker extensionRegistry:extensionRegistry 2462*1b3f573fSAndroid Build Coastguard Worker tag:tag]) { 2463*1b3f573fSAndroid Build Coastguard Worker // it's an endgroup tag 2464*1b3f573fSAndroid Build Coastguard Worker return; 2465*1b3f573fSAndroid Build Coastguard Worker } 2466*1b3f573fSAndroid Build Coastguard Worker } 2467*1b3f573fSAndroid Build Coastguard Worker } // if(!merged) 2468*1b3f573fSAndroid Build Coastguard Worker 2469*1b3f573fSAndroid Build Coastguard Worker } // while(YES) 2470*1b3f573fSAndroid Build Coastguard Worker} 2471*1b3f573fSAndroid Build Coastguard Worker 2472*1b3f573fSAndroid Build Coastguard Worker#pragma mark - MergeFrom Support 2473*1b3f573fSAndroid Build Coastguard Worker 2474*1b3f573fSAndroid Build Coastguard Worker- (void)mergeFrom:(GPBMessage *)other { 2475*1b3f573fSAndroid Build Coastguard Worker Class selfClass = [self class]; 2476*1b3f573fSAndroid Build Coastguard Worker Class otherClass = [other class]; 2477*1b3f573fSAndroid Build Coastguard Worker if (!([selfClass isSubclassOfClass:otherClass] || 2478*1b3f573fSAndroid Build Coastguard Worker [otherClass isSubclassOfClass:selfClass])) { 2479*1b3f573fSAndroid Build Coastguard Worker [NSException raise:NSInvalidArgumentException 2480*1b3f573fSAndroid Build Coastguard Worker format:@"Classes must match %@ != %@", selfClass, otherClass]; 2481*1b3f573fSAndroid Build Coastguard Worker } 2482*1b3f573fSAndroid Build Coastguard Worker 2483*1b3f573fSAndroid Build Coastguard Worker // We assume something will be done and become visible. 2484*1b3f573fSAndroid Build Coastguard Worker GPBBecomeVisibleToAutocreator(self); 2485*1b3f573fSAndroid Build Coastguard Worker 2486*1b3f573fSAndroid Build Coastguard Worker GPBDescriptor *descriptor = [[self class] descriptor]; 2487*1b3f573fSAndroid Build Coastguard Worker 2488*1b3f573fSAndroid Build Coastguard Worker for (GPBFieldDescriptor *field in descriptor->fields_) { 2489*1b3f573fSAndroid Build Coastguard Worker GPBFieldType fieldType = field.fieldType; 2490*1b3f573fSAndroid Build Coastguard Worker if (fieldType == GPBFieldTypeSingle) { 2491*1b3f573fSAndroid Build Coastguard Worker int32_t hasIndex = GPBFieldHasIndex(field); 2492*1b3f573fSAndroid Build Coastguard Worker uint32_t fieldNumber = GPBFieldNumber(field); 2493*1b3f573fSAndroid Build Coastguard Worker if (!GPBGetHasIvar(other, hasIndex, fieldNumber)) { 2494*1b3f573fSAndroid Build Coastguard Worker // Other doesn't have the field set, on to the next. 2495*1b3f573fSAndroid Build Coastguard Worker continue; 2496*1b3f573fSAndroid Build Coastguard Worker } 2497*1b3f573fSAndroid Build Coastguard Worker GPBDataType fieldDataType = GPBGetFieldDataType(field); 2498*1b3f573fSAndroid Build Coastguard Worker switch (fieldDataType) { 2499*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeBool: 2500*1b3f573fSAndroid Build Coastguard Worker GPBSetBoolIvarWithFieldPrivate( 2501*1b3f573fSAndroid Build Coastguard Worker self, field, GPBGetMessageBoolField(other, field)); 2502*1b3f573fSAndroid Build Coastguard Worker break; 2503*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeSFixed32: 2504*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeEnum: 2505*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeInt32: 2506*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeSInt32: 2507*1b3f573fSAndroid Build Coastguard Worker GPBSetInt32IvarWithFieldPrivate( 2508*1b3f573fSAndroid Build Coastguard Worker self, field, GPBGetMessageInt32Field(other, field)); 2509*1b3f573fSAndroid Build Coastguard Worker break; 2510*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeFixed32: 2511*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeUInt32: 2512*1b3f573fSAndroid Build Coastguard Worker GPBSetUInt32IvarWithFieldPrivate( 2513*1b3f573fSAndroid Build Coastguard Worker self, field, GPBGetMessageUInt32Field(other, field)); 2514*1b3f573fSAndroid Build Coastguard Worker break; 2515*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeSFixed64: 2516*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeInt64: 2517*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeSInt64: 2518*1b3f573fSAndroid Build Coastguard Worker GPBSetInt64IvarWithFieldPrivate( 2519*1b3f573fSAndroid Build Coastguard Worker self, field, GPBGetMessageInt64Field(other, field)); 2520*1b3f573fSAndroid Build Coastguard Worker break; 2521*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeFixed64: 2522*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeUInt64: 2523*1b3f573fSAndroid Build Coastguard Worker GPBSetUInt64IvarWithFieldPrivate( 2524*1b3f573fSAndroid Build Coastguard Worker self, field, GPBGetMessageUInt64Field(other, field)); 2525*1b3f573fSAndroid Build Coastguard Worker break; 2526*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeFloat: 2527*1b3f573fSAndroid Build Coastguard Worker GPBSetFloatIvarWithFieldPrivate( 2528*1b3f573fSAndroid Build Coastguard Worker self, field, GPBGetMessageFloatField(other, field)); 2529*1b3f573fSAndroid Build Coastguard Worker break; 2530*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeDouble: 2531*1b3f573fSAndroid Build Coastguard Worker GPBSetDoubleIvarWithFieldPrivate( 2532*1b3f573fSAndroid Build Coastguard Worker self, field, GPBGetMessageDoubleField(other, field)); 2533*1b3f573fSAndroid Build Coastguard Worker break; 2534*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeBytes: 2535*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeString: { 2536*1b3f573fSAndroid Build Coastguard Worker id otherVal = GPBGetObjectIvarWithFieldNoAutocreate(other, field); 2537*1b3f573fSAndroid Build Coastguard Worker GPBSetObjectIvarWithFieldPrivate(self, field, otherVal); 2538*1b3f573fSAndroid Build Coastguard Worker break; 2539*1b3f573fSAndroid Build Coastguard Worker } 2540*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeMessage: 2541*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeGroup: { 2542*1b3f573fSAndroid Build Coastguard Worker id otherVal = GPBGetObjectIvarWithFieldNoAutocreate(other, field); 2543*1b3f573fSAndroid Build Coastguard Worker if (GPBGetHasIvar(self, hasIndex, fieldNumber)) { 2544*1b3f573fSAndroid Build Coastguard Worker GPBMessage *message = 2545*1b3f573fSAndroid Build Coastguard Worker GPBGetObjectIvarWithFieldNoAutocreate(self, field); 2546*1b3f573fSAndroid Build Coastguard Worker [message mergeFrom:otherVal]; 2547*1b3f573fSAndroid Build Coastguard Worker } else { 2548*1b3f573fSAndroid Build Coastguard Worker GPBMessage *message = [otherVal copy]; 2549*1b3f573fSAndroid Build Coastguard Worker GPBSetRetainedObjectIvarWithFieldPrivate(self, field, message); 2550*1b3f573fSAndroid Build Coastguard Worker } 2551*1b3f573fSAndroid Build Coastguard Worker break; 2552*1b3f573fSAndroid Build Coastguard Worker } 2553*1b3f573fSAndroid Build Coastguard Worker } // switch() 2554*1b3f573fSAndroid Build Coastguard Worker } else if (fieldType == GPBFieldTypeRepeated) { 2555*1b3f573fSAndroid Build Coastguard Worker // In the case of a list, they need to be appended, and there is no 2556*1b3f573fSAndroid Build Coastguard Worker // _hasIvar to worry about setting. 2557*1b3f573fSAndroid Build Coastguard Worker id otherArray = 2558*1b3f573fSAndroid Build Coastguard Worker GPBGetObjectIvarWithFieldNoAutocreate(other, field); 2559*1b3f573fSAndroid Build Coastguard Worker if (otherArray) { 2560*1b3f573fSAndroid Build Coastguard Worker GPBDataType fieldDataType = field->description_->dataType; 2561*1b3f573fSAndroid Build Coastguard Worker if (GPBDataTypeIsObject(fieldDataType)) { 2562*1b3f573fSAndroid Build Coastguard Worker NSMutableArray *resultArray = 2563*1b3f573fSAndroid Build Coastguard Worker GetOrCreateArrayIvarWithField(self, field); 2564*1b3f573fSAndroid Build Coastguard Worker [resultArray addObjectsFromArray:otherArray]; 2565*1b3f573fSAndroid Build Coastguard Worker } else if (fieldDataType == GPBDataTypeEnum) { 2566*1b3f573fSAndroid Build Coastguard Worker GPBEnumArray *resultArray = 2567*1b3f573fSAndroid Build Coastguard Worker GetOrCreateArrayIvarWithField(self, field); 2568*1b3f573fSAndroid Build Coastguard Worker [resultArray addRawValuesFromArray:otherArray]; 2569*1b3f573fSAndroid Build Coastguard Worker } else { 2570*1b3f573fSAndroid Build Coastguard Worker // The array type doesn't matter, that all implement 2571*1b3f573fSAndroid Build Coastguard Worker // -addValuesFromArray:. 2572*1b3f573fSAndroid Build Coastguard Worker GPBInt32Array *resultArray = 2573*1b3f573fSAndroid Build Coastguard Worker GetOrCreateArrayIvarWithField(self, field); 2574*1b3f573fSAndroid Build Coastguard Worker [resultArray addValuesFromArray:otherArray]; 2575*1b3f573fSAndroid Build Coastguard Worker } 2576*1b3f573fSAndroid Build Coastguard Worker } 2577*1b3f573fSAndroid Build Coastguard Worker } else { // fieldType = GPBFieldTypeMap 2578*1b3f573fSAndroid Build Coastguard Worker // In the case of a map, they need to be merged, and there is no 2579*1b3f573fSAndroid Build Coastguard Worker // _hasIvar to worry about setting. 2580*1b3f573fSAndroid Build Coastguard Worker id otherDict = GPBGetObjectIvarWithFieldNoAutocreate(other, field); 2581*1b3f573fSAndroid Build Coastguard Worker if (otherDict) { 2582*1b3f573fSAndroid Build Coastguard Worker GPBDataType keyDataType = field.mapKeyDataType; 2583*1b3f573fSAndroid Build Coastguard Worker GPBDataType valueDataType = field->description_->dataType; 2584*1b3f573fSAndroid Build Coastguard Worker if (GPBDataTypeIsObject(keyDataType) && 2585*1b3f573fSAndroid Build Coastguard Worker GPBDataTypeIsObject(valueDataType)) { 2586*1b3f573fSAndroid Build Coastguard Worker NSMutableDictionary *resultDict = 2587*1b3f573fSAndroid Build Coastguard Worker GetOrCreateMapIvarWithField(self, field); 2588*1b3f573fSAndroid Build Coastguard Worker [resultDict addEntriesFromDictionary:otherDict]; 2589*1b3f573fSAndroid Build Coastguard Worker } else if (valueDataType == GPBDataTypeEnum) { 2590*1b3f573fSAndroid Build Coastguard Worker // The exact type doesn't matter, just need to know it is a 2591*1b3f573fSAndroid Build Coastguard Worker // GPB*EnumDictionary. 2592*1b3f573fSAndroid Build Coastguard Worker GPBInt32EnumDictionary *resultDict = 2593*1b3f573fSAndroid Build Coastguard Worker GetOrCreateMapIvarWithField(self, field); 2594*1b3f573fSAndroid Build Coastguard Worker [resultDict addRawEntriesFromDictionary:otherDict]; 2595*1b3f573fSAndroid Build Coastguard Worker } else { 2596*1b3f573fSAndroid Build Coastguard Worker // The exact type doesn't matter, they all implement 2597*1b3f573fSAndroid Build Coastguard Worker // -addEntriesFromDictionary:. 2598*1b3f573fSAndroid Build Coastguard Worker GPBInt32Int32Dictionary *resultDict = 2599*1b3f573fSAndroid Build Coastguard Worker GetOrCreateMapIvarWithField(self, field); 2600*1b3f573fSAndroid Build Coastguard Worker [resultDict addEntriesFromDictionary:otherDict]; 2601*1b3f573fSAndroid Build Coastguard Worker } 2602*1b3f573fSAndroid Build Coastguard Worker } 2603*1b3f573fSAndroid Build Coastguard Worker } // if (fieldType)..else if...else 2604*1b3f573fSAndroid Build Coastguard Worker } // for(fields) 2605*1b3f573fSAndroid Build Coastguard Worker 2606*1b3f573fSAndroid Build Coastguard Worker // Unknown fields. 2607*1b3f573fSAndroid Build Coastguard Worker if (!unknownFields_) { 2608*1b3f573fSAndroid Build Coastguard Worker [self setUnknownFields:other.unknownFields]; 2609*1b3f573fSAndroid Build Coastguard Worker } else { 2610*1b3f573fSAndroid Build Coastguard Worker [unknownFields_ mergeUnknownFields:other.unknownFields]; 2611*1b3f573fSAndroid Build Coastguard Worker } 2612*1b3f573fSAndroid Build Coastguard Worker 2613*1b3f573fSAndroid Build Coastguard Worker // Extensions 2614*1b3f573fSAndroid Build Coastguard Worker 2615*1b3f573fSAndroid Build Coastguard Worker if (other->extensionMap_.count == 0) { 2616*1b3f573fSAndroid Build Coastguard Worker return; 2617*1b3f573fSAndroid Build Coastguard Worker } 2618*1b3f573fSAndroid Build Coastguard Worker 2619*1b3f573fSAndroid Build Coastguard Worker if (extensionMap_ == nil) { 2620*1b3f573fSAndroid Build Coastguard Worker extensionMap_ = 2621*1b3f573fSAndroid Build Coastguard Worker CloneExtensionMap(other->extensionMap_, NSZoneFromPointer(self)); 2622*1b3f573fSAndroid Build Coastguard Worker } else { 2623*1b3f573fSAndroid Build Coastguard Worker for (GPBExtensionDescriptor *extension in other->extensionMap_) { 2624*1b3f573fSAndroid Build Coastguard Worker id otherValue = [other->extensionMap_ objectForKey:extension]; 2625*1b3f573fSAndroid Build Coastguard Worker id value = [extensionMap_ objectForKey:extension]; 2626*1b3f573fSAndroid Build Coastguard Worker BOOL isMessageExtension = GPBExtensionIsMessage(extension); 2627*1b3f573fSAndroid Build Coastguard Worker 2628*1b3f573fSAndroid Build Coastguard Worker if (extension.repeated) { 2629*1b3f573fSAndroid Build Coastguard Worker NSMutableArray *list = value; 2630*1b3f573fSAndroid Build Coastguard Worker if (list == nil) { 2631*1b3f573fSAndroid Build Coastguard Worker list = [[NSMutableArray alloc] init]; 2632*1b3f573fSAndroid Build Coastguard Worker [extensionMap_ setObject:list forKey:extension]; 2633*1b3f573fSAndroid Build Coastguard Worker [list release]; 2634*1b3f573fSAndroid Build Coastguard Worker } 2635*1b3f573fSAndroid Build Coastguard Worker if (isMessageExtension) { 2636*1b3f573fSAndroid Build Coastguard Worker for (GPBMessage *otherListValue in otherValue) { 2637*1b3f573fSAndroid Build Coastguard Worker GPBMessage *copiedValue = [otherListValue copy]; 2638*1b3f573fSAndroid Build Coastguard Worker [list addObject:copiedValue]; 2639*1b3f573fSAndroid Build Coastguard Worker [copiedValue release]; 2640*1b3f573fSAndroid Build Coastguard Worker } 2641*1b3f573fSAndroid Build Coastguard Worker } else { 2642*1b3f573fSAndroid Build Coastguard Worker [list addObjectsFromArray:otherValue]; 2643*1b3f573fSAndroid Build Coastguard Worker } 2644*1b3f573fSAndroid Build Coastguard Worker } else { 2645*1b3f573fSAndroid Build Coastguard Worker if (isMessageExtension) { 2646*1b3f573fSAndroid Build Coastguard Worker if (value) { 2647*1b3f573fSAndroid Build Coastguard Worker [(GPBMessage *)value mergeFrom:(GPBMessage *)otherValue]; 2648*1b3f573fSAndroid Build Coastguard Worker } else { 2649*1b3f573fSAndroid Build Coastguard Worker GPBMessage *copiedValue = [otherValue copy]; 2650*1b3f573fSAndroid Build Coastguard Worker [extensionMap_ setObject:copiedValue forKey:extension]; 2651*1b3f573fSAndroid Build Coastguard Worker [copiedValue release]; 2652*1b3f573fSAndroid Build Coastguard Worker } 2653*1b3f573fSAndroid Build Coastguard Worker } else { 2654*1b3f573fSAndroid Build Coastguard Worker [extensionMap_ setObject:otherValue forKey:extension]; 2655*1b3f573fSAndroid Build Coastguard Worker } 2656*1b3f573fSAndroid Build Coastguard Worker } 2657*1b3f573fSAndroid Build Coastguard Worker 2658*1b3f573fSAndroid Build Coastguard Worker if (isMessageExtension && !extension.isRepeated) { 2659*1b3f573fSAndroid Build Coastguard Worker GPBMessage *autocreatedValue = 2660*1b3f573fSAndroid Build Coastguard Worker [[autocreatedExtensionMap_ objectForKey:extension] retain]; 2661*1b3f573fSAndroid Build Coastguard Worker // Must remove from the map before calling GPBClearMessageAutocreator() 2662*1b3f573fSAndroid Build Coastguard Worker // so that GPBClearMessageAutocreator() knows its safe to clear. 2663*1b3f573fSAndroid Build Coastguard Worker [autocreatedExtensionMap_ removeObjectForKey:extension]; 2664*1b3f573fSAndroid Build Coastguard Worker GPBClearMessageAutocreator(autocreatedValue); 2665*1b3f573fSAndroid Build Coastguard Worker [autocreatedValue release]; 2666*1b3f573fSAndroid Build Coastguard Worker } 2667*1b3f573fSAndroid Build Coastguard Worker } 2668*1b3f573fSAndroid Build Coastguard Worker } 2669*1b3f573fSAndroid Build Coastguard Worker} 2670*1b3f573fSAndroid Build Coastguard Worker 2671*1b3f573fSAndroid Build Coastguard Worker#pragma mark - isEqual: & hash Support 2672*1b3f573fSAndroid Build Coastguard Worker 2673*1b3f573fSAndroid Build Coastguard Worker- (BOOL)isEqual:(id)other { 2674*1b3f573fSAndroid Build Coastguard Worker if (other == self) { 2675*1b3f573fSAndroid Build Coastguard Worker return YES; 2676*1b3f573fSAndroid Build Coastguard Worker } 2677*1b3f573fSAndroid Build Coastguard Worker if (![other isKindOfClass:[GPBMessage class]]) { 2678*1b3f573fSAndroid Build Coastguard Worker return NO; 2679*1b3f573fSAndroid Build Coastguard Worker } 2680*1b3f573fSAndroid Build Coastguard Worker GPBMessage *otherMsg = other; 2681*1b3f573fSAndroid Build Coastguard Worker GPBDescriptor *descriptor = [[self class] descriptor]; 2682*1b3f573fSAndroid Build Coastguard Worker if ([[otherMsg class] descriptor] != descriptor) { 2683*1b3f573fSAndroid Build Coastguard Worker return NO; 2684*1b3f573fSAndroid Build Coastguard Worker } 2685*1b3f573fSAndroid Build Coastguard Worker uint8_t *selfStorage = (uint8_t *)messageStorage_; 2686*1b3f573fSAndroid Build Coastguard Worker uint8_t *otherStorage = (uint8_t *)otherMsg->messageStorage_; 2687*1b3f573fSAndroid Build Coastguard Worker 2688*1b3f573fSAndroid Build Coastguard Worker for (GPBFieldDescriptor *field in descriptor->fields_) { 2689*1b3f573fSAndroid Build Coastguard Worker if (GPBFieldIsMapOrArray(field)) { 2690*1b3f573fSAndroid Build Coastguard Worker // In the case of a list or map, there is no _hasIvar to worry about. 2691*1b3f573fSAndroid Build Coastguard Worker // NOTE: These are NSArray/GPB*Array or NSDictionary/GPB*Dictionary, but 2692*1b3f573fSAndroid Build Coastguard Worker // the type doesn't really matter as the objects all support -count and 2693*1b3f573fSAndroid Build Coastguard Worker // -isEqual:. 2694*1b3f573fSAndroid Build Coastguard Worker NSArray *resultMapOrArray = 2695*1b3f573fSAndroid Build Coastguard Worker GPBGetObjectIvarWithFieldNoAutocreate(self, field); 2696*1b3f573fSAndroid Build Coastguard Worker NSArray *otherMapOrArray = 2697*1b3f573fSAndroid Build Coastguard Worker GPBGetObjectIvarWithFieldNoAutocreate(other, field); 2698*1b3f573fSAndroid Build Coastguard Worker // nil and empty are equal 2699*1b3f573fSAndroid Build Coastguard Worker if (resultMapOrArray.count != 0 || otherMapOrArray.count != 0) { 2700*1b3f573fSAndroid Build Coastguard Worker if (![resultMapOrArray isEqual:otherMapOrArray]) { 2701*1b3f573fSAndroid Build Coastguard Worker return NO; 2702*1b3f573fSAndroid Build Coastguard Worker } 2703*1b3f573fSAndroid Build Coastguard Worker } 2704*1b3f573fSAndroid Build Coastguard Worker } else { // Single field 2705*1b3f573fSAndroid Build Coastguard Worker int32_t hasIndex = GPBFieldHasIndex(field); 2706*1b3f573fSAndroid Build Coastguard Worker uint32_t fieldNum = GPBFieldNumber(field); 2707*1b3f573fSAndroid Build Coastguard Worker BOOL selfHas = GPBGetHasIvar(self, hasIndex, fieldNum); 2708*1b3f573fSAndroid Build Coastguard Worker BOOL otherHas = GPBGetHasIvar(other, hasIndex, fieldNum); 2709*1b3f573fSAndroid Build Coastguard Worker if (selfHas != otherHas) { 2710*1b3f573fSAndroid Build Coastguard Worker return NO; // Differing has values, not equal. 2711*1b3f573fSAndroid Build Coastguard Worker } 2712*1b3f573fSAndroid Build Coastguard Worker if (!selfHas) { 2713*1b3f573fSAndroid Build Coastguard Worker // Same has values, was no, nothing else to check for this field. 2714*1b3f573fSAndroid Build Coastguard Worker continue; 2715*1b3f573fSAndroid Build Coastguard Worker } 2716*1b3f573fSAndroid Build Coastguard Worker // Now compare the values. 2717*1b3f573fSAndroid Build Coastguard Worker GPBDataType fieldDataType = GPBGetFieldDataType(field); 2718*1b3f573fSAndroid Build Coastguard Worker size_t fieldOffset = field->description_->offset; 2719*1b3f573fSAndroid Build Coastguard Worker switch (fieldDataType) { 2720*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeBool: { 2721*1b3f573fSAndroid Build Coastguard Worker // Bools are stored in has_bits to avoid needing explicit space in 2722*1b3f573fSAndroid Build Coastguard Worker // the storage structure. 2723*1b3f573fSAndroid Build Coastguard Worker // (the field number passed to the HasIvar helper doesn't really 2724*1b3f573fSAndroid Build Coastguard Worker // matter since the offset is never negative) 2725*1b3f573fSAndroid Build Coastguard Worker BOOL selfValue = GPBGetHasIvar(self, (int32_t)(fieldOffset), 0); 2726*1b3f573fSAndroid Build Coastguard Worker BOOL otherValue = GPBGetHasIvar(other, (int32_t)(fieldOffset), 0); 2727*1b3f573fSAndroid Build Coastguard Worker if (selfValue != otherValue) { 2728*1b3f573fSAndroid Build Coastguard Worker return NO; 2729*1b3f573fSAndroid Build Coastguard Worker } 2730*1b3f573fSAndroid Build Coastguard Worker break; 2731*1b3f573fSAndroid Build Coastguard Worker } 2732*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeSFixed32: 2733*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeInt32: 2734*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeSInt32: 2735*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeEnum: 2736*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeFixed32: 2737*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeUInt32: 2738*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeFloat: { 2739*1b3f573fSAndroid Build Coastguard Worker GPBInternalCompileAssert(sizeof(float) == sizeof(uint32_t), float_not_32_bits); 2740*1b3f573fSAndroid Build Coastguard Worker // These are all 32bit, signed/unsigned doesn't matter for equality. 2741*1b3f573fSAndroid Build Coastguard Worker uint32_t *selfValPtr = (uint32_t *)&selfStorage[fieldOffset]; 2742*1b3f573fSAndroid Build Coastguard Worker uint32_t *otherValPtr = (uint32_t *)&otherStorage[fieldOffset]; 2743*1b3f573fSAndroid Build Coastguard Worker if (*selfValPtr != *otherValPtr) { 2744*1b3f573fSAndroid Build Coastguard Worker return NO; 2745*1b3f573fSAndroid Build Coastguard Worker } 2746*1b3f573fSAndroid Build Coastguard Worker break; 2747*1b3f573fSAndroid Build Coastguard Worker } 2748*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeSFixed64: 2749*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeInt64: 2750*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeSInt64: 2751*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeFixed64: 2752*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeUInt64: 2753*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeDouble: { 2754*1b3f573fSAndroid Build Coastguard Worker GPBInternalCompileAssert(sizeof(double) == sizeof(uint64_t), double_not_64_bits); 2755*1b3f573fSAndroid Build Coastguard Worker // These are all 64bit, signed/unsigned doesn't matter for equality. 2756*1b3f573fSAndroid Build Coastguard Worker uint64_t *selfValPtr = (uint64_t *)&selfStorage[fieldOffset]; 2757*1b3f573fSAndroid Build Coastguard Worker uint64_t *otherValPtr = (uint64_t *)&otherStorage[fieldOffset]; 2758*1b3f573fSAndroid Build Coastguard Worker if (*selfValPtr != *otherValPtr) { 2759*1b3f573fSAndroid Build Coastguard Worker return NO; 2760*1b3f573fSAndroid Build Coastguard Worker } 2761*1b3f573fSAndroid Build Coastguard Worker break; 2762*1b3f573fSAndroid Build Coastguard Worker } 2763*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeBytes: 2764*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeString: 2765*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeMessage: 2766*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeGroup: { 2767*1b3f573fSAndroid Build Coastguard Worker // Type doesn't matter here, they all implement -isEqual:. 2768*1b3f573fSAndroid Build Coastguard Worker id *selfValPtr = (id *)&selfStorage[fieldOffset]; 2769*1b3f573fSAndroid Build Coastguard Worker id *otherValPtr = (id *)&otherStorage[fieldOffset]; 2770*1b3f573fSAndroid Build Coastguard Worker if (![*selfValPtr isEqual:*otherValPtr]) { 2771*1b3f573fSAndroid Build Coastguard Worker return NO; 2772*1b3f573fSAndroid Build Coastguard Worker } 2773*1b3f573fSAndroid Build Coastguard Worker break; 2774*1b3f573fSAndroid Build Coastguard Worker } 2775*1b3f573fSAndroid Build Coastguard Worker } // switch() 2776*1b3f573fSAndroid Build Coastguard Worker } // if(mapOrArray)...else 2777*1b3f573fSAndroid Build Coastguard Worker } // for(fields) 2778*1b3f573fSAndroid Build Coastguard Worker 2779*1b3f573fSAndroid Build Coastguard Worker // nil and empty are equal 2780*1b3f573fSAndroid Build Coastguard Worker if (extensionMap_.count != 0 || otherMsg->extensionMap_.count != 0) { 2781*1b3f573fSAndroid Build Coastguard Worker if (![extensionMap_ isEqual:otherMsg->extensionMap_]) { 2782*1b3f573fSAndroid Build Coastguard Worker return NO; 2783*1b3f573fSAndroid Build Coastguard Worker } 2784*1b3f573fSAndroid Build Coastguard Worker } 2785*1b3f573fSAndroid Build Coastguard Worker 2786*1b3f573fSAndroid Build Coastguard Worker // nil and empty are equal 2787*1b3f573fSAndroid Build Coastguard Worker GPBUnknownFieldSet *otherUnknowns = otherMsg->unknownFields_; 2788*1b3f573fSAndroid Build Coastguard Worker if ([unknownFields_ countOfFields] != 0 || 2789*1b3f573fSAndroid Build Coastguard Worker [otherUnknowns countOfFields] != 0) { 2790*1b3f573fSAndroid Build Coastguard Worker if (![unknownFields_ isEqual:otherUnknowns]) { 2791*1b3f573fSAndroid Build Coastguard Worker return NO; 2792*1b3f573fSAndroid Build Coastguard Worker } 2793*1b3f573fSAndroid Build Coastguard Worker } 2794*1b3f573fSAndroid Build Coastguard Worker 2795*1b3f573fSAndroid Build Coastguard Worker return YES; 2796*1b3f573fSAndroid Build Coastguard Worker} 2797*1b3f573fSAndroid Build Coastguard Worker 2798*1b3f573fSAndroid Build Coastguard Worker// It is very difficult to implement a generic hash for ProtoBuf messages that 2799*1b3f573fSAndroid Build Coastguard Worker// will perform well. If you need hashing on your ProtoBufs (eg you are using 2800*1b3f573fSAndroid Build Coastguard Worker// them as dictionary keys) you will probably want to implement a ProtoBuf 2801*1b3f573fSAndroid Build Coastguard Worker// message specific hash as a category on your protobuf class. Do not make it a 2802*1b3f573fSAndroid Build Coastguard Worker// category on GPBMessage as you will conflict with this hash, and will possibly 2803*1b3f573fSAndroid Build Coastguard Worker// override hash for all generated protobufs. A good implementation of hash will 2804*1b3f573fSAndroid Build Coastguard Worker// be really fast, so we would recommend only hashing protobufs that have an 2805*1b3f573fSAndroid Build Coastguard Worker// identifier field of some kind that you can easily hash. If you implement 2806*1b3f573fSAndroid Build Coastguard Worker// hash, we would strongly recommend overriding isEqual: in your category as 2807*1b3f573fSAndroid Build Coastguard Worker// well, as the default implementation of isEqual: is extremely slow, and may 2808*1b3f573fSAndroid Build Coastguard Worker// drastically affect performance in large sets. 2809*1b3f573fSAndroid Build Coastguard Worker- (NSUInteger)hash { 2810*1b3f573fSAndroid Build Coastguard Worker GPBDescriptor *descriptor = [[self class] descriptor]; 2811*1b3f573fSAndroid Build Coastguard Worker const NSUInteger prime = 19; 2812*1b3f573fSAndroid Build Coastguard Worker uint8_t *storage = (uint8_t *)messageStorage_; 2813*1b3f573fSAndroid Build Coastguard Worker 2814*1b3f573fSAndroid Build Coastguard Worker // Start with the descriptor and then mix it with some instance info. 2815*1b3f573fSAndroid Build Coastguard Worker // Hopefully that will give a spread based on classes and what fields are set. 2816*1b3f573fSAndroid Build Coastguard Worker NSUInteger result = (NSUInteger)descriptor; 2817*1b3f573fSAndroid Build Coastguard Worker 2818*1b3f573fSAndroid Build Coastguard Worker for (GPBFieldDescriptor *field in descriptor->fields_) { 2819*1b3f573fSAndroid Build Coastguard Worker if (GPBFieldIsMapOrArray(field)) { 2820*1b3f573fSAndroid Build Coastguard Worker // Exact type doesn't matter, just check if there are any elements. 2821*1b3f573fSAndroid Build Coastguard Worker NSArray *mapOrArray = GPBGetObjectIvarWithFieldNoAutocreate(self, field); 2822*1b3f573fSAndroid Build Coastguard Worker NSUInteger count = mapOrArray.count; 2823*1b3f573fSAndroid Build Coastguard Worker if (count) { 2824*1b3f573fSAndroid Build Coastguard Worker // NSArray/NSDictionary use count, use the field number and the count. 2825*1b3f573fSAndroid Build Coastguard Worker result = prime * result + GPBFieldNumber(field); 2826*1b3f573fSAndroid Build Coastguard Worker result = prime * result + count; 2827*1b3f573fSAndroid Build Coastguard Worker } 2828*1b3f573fSAndroid Build Coastguard Worker } else if (GPBGetHasIvarField(self, field)) { 2829*1b3f573fSAndroid Build Coastguard Worker // Just using the field number seemed simple/fast, but then a small 2830*1b3f573fSAndroid Build Coastguard Worker // message class where all the same fields are always set (to different 2831*1b3f573fSAndroid Build Coastguard Worker // things would end up all with the same hash, so pull in some data). 2832*1b3f573fSAndroid Build Coastguard Worker GPBDataType fieldDataType = GPBGetFieldDataType(field); 2833*1b3f573fSAndroid Build Coastguard Worker size_t fieldOffset = field->description_->offset; 2834*1b3f573fSAndroid Build Coastguard Worker switch (fieldDataType) { 2835*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeBool: { 2836*1b3f573fSAndroid Build Coastguard Worker // Bools are stored in has_bits to avoid needing explicit space in 2837*1b3f573fSAndroid Build Coastguard Worker // the storage structure. 2838*1b3f573fSAndroid Build Coastguard Worker // (the field number passed to the HasIvar helper doesn't really 2839*1b3f573fSAndroid Build Coastguard Worker // matter since the offset is never negative) 2840*1b3f573fSAndroid Build Coastguard Worker BOOL value = GPBGetHasIvar(self, (int32_t)(fieldOffset), 0); 2841*1b3f573fSAndroid Build Coastguard Worker result = prime * result + value; 2842*1b3f573fSAndroid Build Coastguard Worker break; 2843*1b3f573fSAndroid Build Coastguard Worker } 2844*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeSFixed32: 2845*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeInt32: 2846*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeSInt32: 2847*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeEnum: 2848*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeFixed32: 2849*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeUInt32: 2850*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeFloat: { 2851*1b3f573fSAndroid Build Coastguard Worker GPBInternalCompileAssert(sizeof(float) == sizeof(uint32_t), float_not_32_bits); 2852*1b3f573fSAndroid Build Coastguard Worker // These are all 32bit, just mix it in. 2853*1b3f573fSAndroid Build Coastguard Worker uint32_t *valPtr = (uint32_t *)&storage[fieldOffset]; 2854*1b3f573fSAndroid Build Coastguard Worker result = prime * result + *valPtr; 2855*1b3f573fSAndroid Build Coastguard Worker break; 2856*1b3f573fSAndroid Build Coastguard Worker } 2857*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeSFixed64: 2858*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeInt64: 2859*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeSInt64: 2860*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeFixed64: 2861*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeUInt64: 2862*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeDouble: { 2863*1b3f573fSAndroid Build Coastguard Worker GPBInternalCompileAssert(sizeof(double) == sizeof(uint64_t), double_not_64_bits); 2864*1b3f573fSAndroid Build Coastguard Worker // These are all 64bit, just mix what fits into an NSUInteger in. 2865*1b3f573fSAndroid Build Coastguard Worker uint64_t *valPtr = (uint64_t *)&storage[fieldOffset]; 2866*1b3f573fSAndroid Build Coastguard Worker result = prime * result + (NSUInteger)(*valPtr); 2867*1b3f573fSAndroid Build Coastguard Worker break; 2868*1b3f573fSAndroid Build Coastguard Worker } 2869*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeBytes: 2870*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeString: { 2871*1b3f573fSAndroid Build Coastguard Worker // Type doesn't matter here, they both implement -hash:. 2872*1b3f573fSAndroid Build Coastguard Worker id *valPtr = (id *)&storage[fieldOffset]; 2873*1b3f573fSAndroid Build Coastguard Worker result = prime * result + [*valPtr hash]; 2874*1b3f573fSAndroid Build Coastguard Worker break; 2875*1b3f573fSAndroid Build Coastguard Worker } 2876*1b3f573fSAndroid Build Coastguard Worker 2877*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeMessage: 2878*1b3f573fSAndroid Build Coastguard Worker case GPBDataTypeGroup: { 2879*1b3f573fSAndroid Build Coastguard Worker GPBMessage **valPtr = (GPBMessage **)&storage[fieldOffset]; 2880*1b3f573fSAndroid Build Coastguard Worker // Could call -hash on the sub message, but that could recurse pretty 2881*1b3f573fSAndroid Build Coastguard Worker // deep; follow the lead of NSArray/NSDictionary and don't really 2882*1b3f573fSAndroid Build Coastguard Worker // recurse for hash, instead use the field number and the descriptor 2883*1b3f573fSAndroid Build Coastguard Worker // of the sub message. Yes, this could suck for a bunch of messages 2884*1b3f573fSAndroid Build Coastguard Worker // where they all only differ in the sub messages, but if you are 2885*1b3f573fSAndroid Build Coastguard Worker // using a message with sub messages for something that needs -hash, 2886*1b3f573fSAndroid Build Coastguard Worker // odds are you are also copying them as keys, and that deep copy 2887*1b3f573fSAndroid Build Coastguard Worker // will also suck. 2888*1b3f573fSAndroid Build Coastguard Worker result = prime * result + GPBFieldNumber(field); 2889*1b3f573fSAndroid Build Coastguard Worker result = prime * result + (NSUInteger)[[*valPtr class] descriptor]; 2890*1b3f573fSAndroid Build Coastguard Worker break; 2891*1b3f573fSAndroid Build Coastguard Worker } 2892*1b3f573fSAndroid Build Coastguard Worker } // switch() 2893*1b3f573fSAndroid Build Coastguard Worker } 2894*1b3f573fSAndroid Build Coastguard Worker } 2895*1b3f573fSAndroid Build Coastguard Worker 2896*1b3f573fSAndroid Build Coastguard Worker // Unknowns and extensions are not included. 2897*1b3f573fSAndroid Build Coastguard Worker 2898*1b3f573fSAndroid Build Coastguard Worker return result; 2899*1b3f573fSAndroid Build Coastguard Worker} 2900*1b3f573fSAndroid Build Coastguard Worker 2901*1b3f573fSAndroid Build Coastguard Worker#pragma mark - Description Support 2902*1b3f573fSAndroid Build Coastguard Worker 2903*1b3f573fSAndroid Build Coastguard Worker- (NSString *)description { 2904*1b3f573fSAndroid Build Coastguard Worker NSString *textFormat = GPBTextFormatForMessage(self, @" "); 2905*1b3f573fSAndroid Build Coastguard Worker NSString *description = [NSString 2906*1b3f573fSAndroid Build Coastguard Worker stringWithFormat:@"<%@ %p>: {\n%@}", [self class], self, textFormat]; 2907*1b3f573fSAndroid Build Coastguard Worker return description; 2908*1b3f573fSAndroid Build Coastguard Worker} 2909*1b3f573fSAndroid Build Coastguard Worker 2910*1b3f573fSAndroid Build Coastguard Worker#if defined(DEBUG) && DEBUG 2911*1b3f573fSAndroid Build Coastguard Worker 2912*1b3f573fSAndroid Build Coastguard Worker// Xcode 5.1 added support for custom quick look info. 2913*1b3f573fSAndroid Build Coastguard Worker// https://developer.apple.com/library/ios/documentation/IDEs/Conceptual/CustomClassDisplay_in_QuickLook/CH01-quick_look_for_custom_objects/CH01-quick_look_for_custom_objects.html#//apple_ref/doc/uid/TP40014001-CH2-SW1 2914*1b3f573fSAndroid Build Coastguard Worker- (id)debugQuickLookObject { 2915*1b3f573fSAndroid Build Coastguard Worker return GPBTextFormatForMessage(self, nil); 2916*1b3f573fSAndroid Build Coastguard Worker} 2917*1b3f573fSAndroid Build Coastguard Worker 2918*1b3f573fSAndroid Build Coastguard Worker#endif // DEBUG 2919*1b3f573fSAndroid Build Coastguard Worker 2920*1b3f573fSAndroid Build Coastguard Worker#pragma mark - SerializedSize 2921*1b3f573fSAndroid Build Coastguard Worker 2922*1b3f573fSAndroid Build Coastguard Worker- (size_t)serializedSize { 2923*1b3f573fSAndroid Build Coastguard Worker GPBDescriptor *descriptor = [[self class] descriptor]; 2924*1b3f573fSAndroid Build Coastguard Worker size_t result = 0; 2925*1b3f573fSAndroid Build Coastguard Worker 2926*1b3f573fSAndroid Build Coastguard Worker // Has check is done explicitly, so GPBGetObjectIvarWithFieldNoAutocreate() 2927*1b3f573fSAndroid Build Coastguard Worker // avoids doing the has check again. 2928*1b3f573fSAndroid Build Coastguard Worker 2929*1b3f573fSAndroid Build Coastguard Worker // Fields. 2930*1b3f573fSAndroid Build Coastguard Worker for (GPBFieldDescriptor *fieldDescriptor in descriptor->fields_) { 2931*1b3f573fSAndroid Build Coastguard Worker GPBFieldType fieldType = fieldDescriptor.fieldType; 2932*1b3f573fSAndroid Build Coastguard Worker GPBDataType fieldDataType = GPBGetFieldDataType(fieldDescriptor); 2933*1b3f573fSAndroid Build Coastguard Worker 2934*1b3f573fSAndroid Build Coastguard Worker // Single Fields 2935*1b3f573fSAndroid Build Coastguard Worker if (fieldType == GPBFieldTypeSingle) { 2936*1b3f573fSAndroid Build Coastguard Worker BOOL selfHas = GPBGetHasIvarField(self, fieldDescriptor); 2937*1b3f573fSAndroid Build Coastguard Worker if (!selfHas) { 2938*1b3f573fSAndroid Build Coastguard Worker continue; // Nothing to do. 2939*1b3f573fSAndroid Build Coastguard Worker } 2940*1b3f573fSAndroid Build Coastguard Worker 2941*1b3f573fSAndroid Build Coastguard Worker uint32_t fieldNumber = GPBFieldNumber(fieldDescriptor); 2942*1b3f573fSAndroid Build Coastguard Worker 2943*1b3f573fSAndroid Build Coastguard Worker switch (fieldDataType) { 2944*1b3f573fSAndroid Build Coastguard Worker#define CASE_SINGLE_POD(NAME, TYPE, FUNC_TYPE) \ 2945*1b3f573fSAndroid Build Coastguard Worker case GPBDataType##NAME: { \ 2946*1b3f573fSAndroid Build Coastguard Worker TYPE fieldVal = GPBGetMessage##FUNC_TYPE##Field(self, fieldDescriptor); \ 2947*1b3f573fSAndroid Build Coastguard Worker result += GPBCompute##NAME##Size(fieldNumber, fieldVal); \ 2948*1b3f573fSAndroid Build Coastguard Worker break; \ 2949*1b3f573fSAndroid Build Coastguard Worker } 2950*1b3f573fSAndroid Build Coastguard Worker#define CASE_SINGLE_OBJECT(NAME) \ 2951*1b3f573fSAndroid Build Coastguard Worker case GPBDataType##NAME: { \ 2952*1b3f573fSAndroid Build Coastguard Worker id fieldVal = GPBGetObjectIvarWithFieldNoAutocreate(self, fieldDescriptor); \ 2953*1b3f573fSAndroid Build Coastguard Worker result += GPBCompute##NAME##Size(fieldNumber, fieldVal); \ 2954*1b3f573fSAndroid Build Coastguard Worker break; \ 2955*1b3f573fSAndroid Build Coastguard Worker } 2956*1b3f573fSAndroid Build Coastguard Worker CASE_SINGLE_POD(Bool, BOOL, Bool) 2957*1b3f573fSAndroid Build Coastguard Worker CASE_SINGLE_POD(Fixed32, uint32_t, UInt32) 2958*1b3f573fSAndroid Build Coastguard Worker CASE_SINGLE_POD(SFixed32, int32_t, Int32) 2959*1b3f573fSAndroid Build Coastguard Worker CASE_SINGLE_POD(Float, float, Float) 2960*1b3f573fSAndroid Build Coastguard Worker CASE_SINGLE_POD(Fixed64, uint64_t, UInt64) 2961*1b3f573fSAndroid Build Coastguard Worker CASE_SINGLE_POD(SFixed64, int64_t, Int64) 2962*1b3f573fSAndroid Build Coastguard Worker CASE_SINGLE_POD(Double, double, Double) 2963*1b3f573fSAndroid Build Coastguard Worker CASE_SINGLE_POD(Int32, int32_t, Int32) 2964*1b3f573fSAndroid Build Coastguard Worker CASE_SINGLE_POD(Int64, int64_t, Int64) 2965*1b3f573fSAndroid Build Coastguard Worker CASE_SINGLE_POD(SInt32, int32_t, Int32) 2966*1b3f573fSAndroid Build Coastguard Worker CASE_SINGLE_POD(SInt64, int64_t, Int64) 2967*1b3f573fSAndroid Build Coastguard Worker CASE_SINGLE_POD(UInt32, uint32_t, UInt32) 2968*1b3f573fSAndroid Build Coastguard Worker CASE_SINGLE_POD(UInt64, uint64_t, UInt64) 2969*1b3f573fSAndroid Build Coastguard Worker CASE_SINGLE_OBJECT(Bytes) 2970*1b3f573fSAndroid Build Coastguard Worker CASE_SINGLE_OBJECT(String) 2971*1b3f573fSAndroid Build Coastguard Worker CASE_SINGLE_OBJECT(Message) 2972*1b3f573fSAndroid Build Coastguard Worker CASE_SINGLE_OBJECT(Group) 2973*1b3f573fSAndroid Build Coastguard Worker CASE_SINGLE_POD(Enum, int32_t, Int32) 2974*1b3f573fSAndroid Build Coastguard Worker#undef CASE_SINGLE_POD 2975*1b3f573fSAndroid Build Coastguard Worker#undef CASE_SINGLE_OBJECT 2976*1b3f573fSAndroid Build Coastguard Worker } 2977*1b3f573fSAndroid Build Coastguard Worker 2978*1b3f573fSAndroid Build Coastguard Worker // Repeated Fields 2979*1b3f573fSAndroid Build Coastguard Worker } else if (fieldType == GPBFieldTypeRepeated) { 2980*1b3f573fSAndroid Build Coastguard Worker id genericArray = 2981*1b3f573fSAndroid Build Coastguard Worker GPBGetObjectIvarWithFieldNoAutocreate(self, fieldDescriptor); 2982*1b3f573fSAndroid Build Coastguard Worker NSUInteger count = [genericArray count]; 2983*1b3f573fSAndroid Build Coastguard Worker if (count == 0) { 2984*1b3f573fSAndroid Build Coastguard Worker continue; // Nothing to add. 2985*1b3f573fSAndroid Build Coastguard Worker } 2986*1b3f573fSAndroid Build Coastguard Worker __block size_t dataSize = 0; 2987*1b3f573fSAndroid Build Coastguard Worker 2988*1b3f573fSAndroid Build Coastguard Worker switch (fieldDataType) { 2989*1b3f573fSAndroid Build Coastguard Worker#define CASE_REPEATED_POD(NAME, TYPE, ARRAY_TYPE) \ 2990*1b3f573fSAndroid Build Coastguard Worker CASE_REPEATED_POD_EXTRA(NAME, TYPE, ARRAY_TYPE, ) 2991*1b3f573fSAndroid Build Coastguard Worker#define CASE_REPEATED_POD_EXTRA(NAME, TYPE, ARRAY_TYPE, ARRAY_ACCESSOR_NAME) \ 2992*1b3f573fSAndroid Build Coastguard Worker case GPBDataType##NAME: { \ 2993*1b3f573fSAndroid Build Coastguard Worker GPB##ARRAY_TYPE##Array *array = genericArray; \ 2994*1b3f573fSAndroid Build Coastguard Worker [array enumerate##ARRAY_ACCESSOR_NAME##ValuesWithBlock:^(TYPE value, NSUInteger idx, BOOL *stop) { \ 2995*1b3f573fSAndroid Build Coastguard Worker _Pragma("unused(idx, stop)"); \ 2996*1b3f573fSAndroid Build Coastguard Worker dataSize += GPBCompute##NAME##SizeNoTag(value); \ 2997*1b3f573fSAndroid Build Coastguard Worker }]; \ 2998*1b3f573fSAndroid Build Coastguard Worker break; \ 2999*1b3f573fSAndroid Build Coastguard Worker } 3000*1b3f573fSAndroid Build Coastguard Worker#define CASE_REPEATED_OBJECT(NAME) \ 3001*1b3f573fSAndroid Build Coastguard Worker case GPBDataType##NAME: { \ 3002*1b3f573fSAndroid Build Coastguard Worker for (id value in genericArray) { \ 3003*1b3f573fSAndroid Build Coastguard Worker dataSize += GPBCompute##NAME##SizeNoTag(value); \ 3004*1b3f573fSAndroid Build Coastguard Worker } \ 3005*1b3f573fSAndroid Build Coastguard Worker break; \ 3006*1b3f573fSAndroid Build Coastguard Worker } 3007*1b3f573fSAndroid Build Coastguard Worker CASE_REPEATED_POD(Bool, BOOL, Bool) 3008*1b3f573fSAndroid Build Coastguard Worker CASE_REPEATED_POD(Fixed32, uint32_t, UInt32) 3009*1b3f573fSAndroid Build Coastguard Worker CASE_REPEATED_POD(SFixed32, int32_t, Int32) 3010*1b3f573fSAndroid Build Coastguard Worker CASE_REPEATED_POD(Float, float, Float) 3011*1b3f573fSAndroid Build Coastguard Worker CASE_REPEATED_POD(Fixed64, uint64_t, UInt64) 3012*1b3f573fSAndroid Build Coastguard Worker CASE_REPEATED_POD(SFixed64, int64_t, Int64) 3013*1b3f573fSAndroid Build Coastguard Worker CASE_REPEATED_POD(Double, double, Double) 3014*1b3f573fSAndroid Build Coastguard Worker CASE_REPEATED_POD(Int32, int32_t, Int32) 3015*1b3f573fSAndroid Build Coastguard Worker CASE_REPEATED_POD(Int64, int64_t, Int64) 3016*1b3f573fSAndroid Build Coastguard Worker CASE_REPEATED_POD(SInt32, int32_t, Int32) 3017*1b3f573fSAndroid Build Coastguard Worker CASE_REPEATED_POD(SInt64, int64_t, Int64) 3018*1b3f573fSAndroid Build Coastguard Worker CASE_REPEATED_POD(UInt32, uint32_t, UInt32) 3019*1b3f573fSAndroid Build Coastguard Worker CASE_REPEATED_POD(UInt64, uint64_t, UInt64) 3020*1b3f573fSAndroid Build Coastguard Worker CASE_REPEATED_OBJECT(Bytes) 3021*1b3f573fSAndroid Build Coastguard Worker CASE_REPEATED_OBJECT(String) 3022*1b3f573fSAndroid Build Coastguard Worker CASE_REPEATED_OBJECT(Message) 3023*1b3f573fSAndroid Build Coastguard Worker CASE_REPEATED_OBJECT(Group) 3024*1b3f573fSAndroid Build Coastguard Worker CASE_REPEATED_POD_EXTRA(Enum, int32_t, Enum, Raw) 3025*1b3f573fSAndroid Build Coastguard Worker#undef CASE_REPEATED_POD 3026*1b3f573fSAndroid Build Coastguard Worker#undef CASE_REPEATED_POD_EXTRA 3027*1b3f573fSAndroid Build Coastguard Worker#undef CASE_REPEATED_OBJECT 3028*1b3f573fSAndroid Build Coastguard Worker } // switch 3029*1b3f573fSAndroid Build Coastguard Worker result += dataSize; 3030*1b3f573fSAndroid Build Coastguard Worker size_t tagSize = GPBComputeTagSize(GPBFieldNumber(fieldDescriptor)); 3031*1b3f573fSAndroid Build Coastguard Worker if (fieldDataType == GPBDataTypeGroup) { 3032*1b3f573fSAndroid Build Coastguard Worker // Groups have both a start and an end tag. 3033*1b3f573fSAndroid Build Coastguard Worker tagSize *= 2; 3034*1b3f573fSAndroid Build Coastguard Worker } 3035*1b3f573fSAndroid Build Coastguard Worker if (fieldDescriptor.isPackable) { 3036*1b3f573fSAndroid Build Coastguard Worker result += tagSize; 3037*1b3f573fSAndroid Build Coastguard Worker result += GPBComputeSizeTSizeAsInt32NoTag(dataSize); 3038*1b3f573fSAndroid Build Coastguard Worker } else { 3039*1b3f573fSAndroid Build Coastguard Worker result += count * tagSize; 3040*1b3f573fSAndroid Build Coastguard Worker } 3041*1b3f573fSAndroid Build Coastguard Worker 3042*1b3f573fSAndroid Build Coastguard Worker // Map<> Fields 3043*1b3f573fSAndroid Build Coastguard Worker } else { // fieldType == GPBFieldTypeMap 3044*1b3f573fSAndroid Build Coastguard Worker if (GPBDataTypeIsObject(fieldDataType) && 3045*1b3f573fSAndroid Build Coastguard Worker (fieldDescriptor.mapKeyDataType == GPBDataTypeString)) { 3046*1b3f573fSAndroid Build Coastguard Worker // If key type was string, then the map is an NSDictionary. 3047*1b3f573fSAndroid Build Coastguard Worker NSDictionary *map = 3048*1b3f573fSAndroid Build Coastguard Worker GPBGetObjectIvarWithFieldNoAutocreate(self, fieldDescriptor); 3049*1b3f573fSAndroid Build Coastguard Worker if (map) { 3050*1b3f573fSAndroid Build Coastguard Worker result += GPBDictionaryComputeSizeInternalHelper(map, fieldDescriptor); 3051*1b3f573fSAndroid Build Coastguard Worker } 3052*1b3f573fSAndroid Build Coastguard Worker } else { 3053*1b3f573fSAndroid Build Coastguard Worker // Type will be GPB*GroupDictionary, exact type doesn't matter. 3054*1b3f573fSAndroid Build Coastguard Worker GPBInt32Int32Dictionary *map = 3055*1b3f573fSAndroid Build Coastguard Worker GPBGetObjectIvarWithFieldNoAutocreate(self, fieldDescriptor); 3056*1b3f573fSAndroid Build Coastguard Worker result += [map computeSerializedSizeAsField:fieldDescriptor]; 3057*1b3f573fSAndroid Build Coastguard Worker } 3058*1b3f573fSAndroid Build Coastguard Worker } 3059*1b3f573fSAndroid Build Coastguard Worker } // for(fields) 3060*1b3f573fSAndroid Build Coastguard Worker 3061*1b3f573fSAndroid Build Coastguard Worker // Add any unknown fields. 3062*1b3f573fSAndroid Build Coastguard Worker if (descriptor.wireFormat) { 3063*1b3f573fSAndroid Build Coastguard Worker result += [unknownFields_ serializedSizeAsMessageSet]; 3064*1b3f573fSAndroid Build Coastguard Worker } else { 3065*1b3f573fSAndroid Build Coastguard Worker result += [unknownFields_ serializedSize]; 3066*1b3f573fSAndroid Build Coastguard Worker } 3067*1b3f573fSAndroid Build Coastguard Worker 3068*1b3f573fSAndroid Build Coastguard Worker // Add any extensions. 3069*1b3f573fSAndroid Build Coastguard Worker for (GPBExtensionDescriptor *extension in extensionMap_) { 3070*1b3f573fSAndroid Build Coastguard Worker id value = [extensionMap_ objectForKey:extension]; 3071*1b3f573fSAndroid Build Coastguard Worker result += GPBComputeExtensionSerializedSizeIncludingTag(extension, value); 3072*1b3f573fSAndroid Build Coastguard Worker } 3073*1b3f573fSAndroid Build Coastguard Worker 3074*1b3f573fSAndroid Build Coastguard Worker return result; 3075*1b3f573fSAndroid Build Coastguard Worker} 3076*1b3f573fSAndroid Build Coastguard Worker 3077*1b3f573fSAndroid Build Coastguard Worker#pragma mark - Resolve Methods Support 3078*1b3f573fSAndroid Build Coastguard Worker 3079*1b3f573fSAndroid Build Coastguard Workertypedef struct ResolveIvarAccessorMethodResult { 3080*1b3f573fSAndroid Build Coastguard Worker IMP impToAdd; 3081*1b3f573fSAndroid Build Coastguard Worker SEL encodingSelector; 3082*1b3f573fSAndroid Build Coastguard Worker} ResolveIvarAccessorMethodResult; 3083*1b3f573fSAndroid Build Coastguard Worker 3084*1b3f573fSAndroid Build Coastguard Worker// |field| can be __unsafe_unretained because they are created at startup 3085*1b3f573fSAndroid Build Coastguard Worker// and are essentially global. No need to pay for retain/release when 3086*1b3f573fSAndroid Build Coastguard Worker// they are captured in blocks. 3087*1b3f573fSAndroid Build Coastguard Workerstatic void ResolveIvarGet(__unsafe_unretained GPBFieldDescriptor *field, 3088*1b3f573fSAndroid Build Coastguard Worker ResolveIvarAccessorMethodResult *result) { 3089*1b3f573fSAndroid Build Coastguard Worker GPBDataType fieldDataType = GPBGetFieldDataType(field); 3090*1b3f573fSAndroid Build Coastguard Worker switch (fieldDataType) { 3091*1b3f573fSAndroid Build Coastguard Worker#define CASE_GET(NAME, TYPE, TRUE_NAME) \ 3092*1b3f573fSAndroid Build Coastguard Worker case GPBDataType##NAME: { \ 3093*1b3f573fSAndroid Build Coastguard Worker result->impToAdd = imp_implementationWithBlock(^(id obj) { \ 3094*1b3f573fSAndroid Build Coastguard Worker return GPBGetMessage##TRUE_NAME##Field(obj, field); \ 3095*1b3f573fSAndroid Build Coastguard Worker }); \ 3096*1b3f573fSAndroid Build Coastguard Worker result->encodingSelector = @selector(get##NAME); \ 3097*1b3f573fSAndroid Build Coastguard Worker break; \ 3098*1b3f573fSAndroid Build Coastguard Worker } 3099*1b3f573fSAndroid Build Coastguard Worker#define CASE_GET_OBJECT(NAME, TYPE, TRUE_NAME) \ 3100*1b3f573fSAndroid Build Coastguard Worker case GPBDataType##NAME: { \ 3101*1b3f573fSAndroid Build Coastguard Worker result->impToAdd = imp_implementationWithBlock(^(id obj) { \ 3102*1b3f573fSAndroid Build Coastguard Worker return GPBGetObjectIvarWithField(obj, field); \ 3103*1b3f573fSAndroid Build Coastguard Worker }); \ 3104*1b3f573fSAndroid Build Coastguard Worker result->encodingSelector = @selector(get##NAME); \ 3105*1b3f573fSAndroid Build Coastguard Worker break; \ 3106*1b3f573fSAndroid Build Coastguard Worker } 3107*1b3f573fSAndroid Build Coastguard Worker CASE_GET(Bool, BOOL, Bool) 3108*1b3f573fSAndroid Build Coastguard Worker CASE_GET(Fixed32, uint32_t, UInt32) 3109*1b3f573fSAndroid Build Coastguard Worker CASE_GET(SFixed32, int32_t, Int32) 3110*1b3f573fSAndroid Build Coastguard Worker CASE_GET(Float, float, Float) 3111*1b3f573fSAndroid Build Coastguard Worker CASE_GET(Fixed64, uint64_t, UInt64) 3112*1b3f573fSAndroid Build Coastguard Worker CASE_GET(SFixed64, int64_t, Int64) 3113*1b3f573fSAndroid Build Coastguard Worker CASE_GET(Double, double, Double) 3114*1b3f573fSAndroid Build Coastguard Worker CASE_GET(Int32, int32_t, Int32) 3115*1b3f573fSAndroid Build Coastguard Worker CASE_GET(Int64, int64_t, Int64) 3116*1b3f573fSAndroid Build Coastguard Worker CASE_GET(SInt32, int32_t, Int32) 3117*1b3f573fSAndroid Build Coastguard Worker CASE_GET(SInt64, int64_t, Int64) 3118*1b3f573fSAndroid Build Coastguard Worker CASE_GET(UInt32, uint32_t, UInt32) 3119*1b3f573fSAndroid Build Coastguard Worker CASE_GET(UInt64, uint64_t, UInt64) 3120*1b3f573fSAndroid Build Coastguard Worker CASE_GET_OBJECT(Bytes, id, Object) 3121*1b3f573fSAndroid Build Coastguard Worker CASE_GET_OBJECT(String, id, Object) 3122*1b3f573fSAndroid Build Coastguard Worker CASE_GET_OBJECT(Message, id, Object) 3123*1b3f573fSAndroid Build Coastguard Worker CASE_GET_OBJECT(Group, id, Object) 3124*1b3f573fSAndroid Build Coastguard Worker CASE_GET(Enum, int32_t, Enum) 3125*1b3f573fSAndroid Build Coastguard Worker#undef CASE_GET 3126*1b3f573fSAndroid Build Coastguard Worker } 3127*1b3f573fSAndroid Build Coastguard Worker} 3128*1b3f573fSAndroid Build Coastguard Worker 3129*1b3f573fSAndroid Build Coastguard Worker// See comment about __unsafe_unretained on ResolveIvarGet. 3130*1b3f573fSAndroid Build Coastguard Workerstatic void ResolveIvarSet(__unsafe_unretained GPBFieldDescriptor *field, 3131*1b3f573fSAndroid Build Coastguard Worker ResolveIvarAccessorMethodResult *result) { 3132*1b3f573fSAndroid Build Coastguard Worker GPBDataType fieldDataType = GPBGetFieldDataType(field); 3133*1b3f573fSAndroid Build Coastguard Worker switch (fieldDataType) { 3134*1b3f573fSAndroid Build Coastguard Worker#define CASE_SET(NAME, TYPE, TRUE_NAME) \ 3135*1b3f573fSAndroid Build Coastguard Worker case GPBDataType##NAME: { \ 3136*1b3f573fSAndroid Build Coastguard Worker result->impToAdd = imp_implementationWithBlock(^(id obj, TYPE value) { \ 3137*1b3f573fSAndroid Build Coastguard Worker return GPBSet##TRUE_NAME##IvarWithFieldPrivate(obj, field, value); \ 3138*1b3f573fSAndroid Build Coastguard Worker }); \ 3139*1b3f573fSAndroid Build Coastguard Worker result->encodingSelector = @selector(set##NAME:); \ 3140*1b3f573fSAndroid Build Coastguard Worker break; \ 3141*1b3f573fSAndroid Build Coastguard Worker } 3142*1b3f573fSAndroid Build Coastguard Worker#define CASE_SET_COPY(NAME) \ 3143*1b3f573fSAndroid Build Coastguard Worker case GPBDataType##NAME: { \ 3144*1b3f573fSAndroid Build Coastguard Worker result->impToAdd = imp_implementationWithBlock(^(id obj, id value) { \ 3145*1b3f573fSAndroid Build Coastguard Worker return GPBSetRetainedObjectIvarWithFieldPrivate(obj, field, [value copy]); \ 3146*1b3f573fSAndroid Build Coastguard Worker }); \ 3147*1b3f573fSAndroid Build Coastguard Worker result->encodingSelector = @selector(set##NAME:); \ 3148*1b3f573fSAndroid Build Coastguard Worker break; \ 3149*1b3f573fSAndroid Build Coastguard Worker } 3150*1b3f573fSAndroid Build Coastguard Worker CASE_SET(Bool, BOOL, Bool) 3151*1b3f573fSAndroid Build Coastguard Worker CASE_SET(Fixed32, uint32_t, UInt32) 3152*1b3f573fSAndroid Build Coastguard Worker CASE_SET(SFixed32, int32_t, Int32) 3153*1b3f573fSAndroid Build Coastguard Worker CASE_SET(Float, float, Float) 3154*1b3f573fSAndroid Build Coastguard Worker CASE_SET(Fixed64, uint64_t, UInt64) 3155*1b3f573fSAndroid Build Coastguard Worker CASE_SET(SFixed64, int64_t, Int64) 3156*1b3f573fSAndroid Build Coastguard Worker CASE_SET(Double, double, Double) 3157*1b3f573fSAndroid Build Coastguard Worker CASE_SET(Int32, int32_t, Int32) 3158*1b3f573fSAndroid Build Coastguard Worker CASE_SET(Int64, int64_t, Int64) 3159*1b3f573fSAndroid Build Coastguard Worker CASE_SET(SInt32, int32_t, Int32) 3160*1b3f573fSAndroid Build Coastguard Worker CASE_SET(SInt64, int64_t, Int64) 3161*1b3f573fSAndroid Build Coastguard Worker CASE_SET(UInt32, uint32_t, UInt32) 3162*1b3f573fSAndroid Build Coastguard Worker CASE_SET(UInt64, uint64_t, UInt64) 3163*1b3f573fSAndroid Build Coastguard Worker CASE_SET_COPY(Bytes) 3164*1b3f573fSAndroid Build Coastguard Worker CASE_SET_COPY(String) 3165*1b3f573fSAndroid Build Coastguard Worker CASE_SET(Message, id, Object) 3166*1b3f573fSAndroid Build Coastguard Worker CASE_SET(Group, id, Object) 3167*1b3f573fSAndroid Build Coastguard Worker CASE_SET(Enum, int32_t, Enum) 3168*1b3f573fSAndroid Build Coastguard Worker#undef CASE_SET 3169*1b3f573fSAndroid Build Coastguard Worker } 3170*1b3f573fSAndroid Build Coastguard Worker} 3171*1b3f573fSAndroid Build Coastguard Worker 3172*1b3f573fSAndroid Build Coastguard Worker+ (BOOL)resolveInstanceMethod:(SEL)sel { 3173*1b3f573fSAndroid Build Coastguard Worker const GPBDescriptor *descriptor = [self descriptor]; 3174*1b3f573fSAndroid Build Coastguard Worker if (!descriptor) { 3175*1b3f573fSAndroid Build Coastguard Worker return [super resolveInstanceMethod:sel]; 3176*1b3f573fSAndroid Build Coastguard Worker } 3177*1b3f573fSAndroid Build Coastguard Worker 3178*1b3f573fSAndroid Build Coastguard Worker // NOTE: hasOrCountSel_/setHasSel_ will be NULL if the field for the given 3179*1b3f573fSAndroid Build Coastguard Worker // message should not have has support (done in GPBDescriptor.m), so there is 3180*1b3f573fSAndroid Build Coastguard Worker // no need for checks here to see if has*/setHas* are allowed. 3181*1b3f573fSAndroid Build Coastguard Worker ResolveIvarAccessorMethodResult result = {NULL, NULL}; 3182*1b3f573fSAndroid Build Coastguard Worker 3183*1b3f573fSAndroid Build Coastguard Worker // See comment about __unsafe_unretained on ResolveIvarGet. 3184*1b3f573fSAndroid Build Coastguard Worker for (__unsafe_unretained GPBFieldDescriptor *field in descriptor->fields_) { 3185*1b3f573fSAndroid Build Coastguard Worker BOOL isMapOrArray = GPBFieldIsMapOrArray(field); 3186*1b3f573fSAndroid Build Coastguard Worker if (!isMapOrArray) { 3187*1b3f573fSAndroid Build Coastguard Worker // Single fields. 3188*1b3f573fSAndroid Build Coastguard Worker if (sel == field->getSel_) { 3189*1b3f573fSAndroid Build Coastguard Worker ResolveIvarGet(field, &result); 3190*1b3f573fSAndroid Build Coastguard Worker break; 3191*1b3f573fSAndroid Build Coastguard Worker } else if (sel == field->setSel_) { 3192*1b3f573fSAndroid Build Coastguard Worker ResolveIvarSet(field, &result); 3193*1b3f573fSAndroid Build Coastguard Worker break; 3194*1b3f573fSAndroid Build Coastguard Worker } else if (sel == field->hasOrCountSel_) { 3195*1b3f573fSAndroid Build Coastguard Worker int32_t index = GPBFieldHasIndex(field); 3196*1b3f573fSAndroid Build Coastguard Worker uint32_t fieldNum = GPBFieldNumber(field); 3197*1b3f573fSAndroid Build Coastguard Worker result.impToAdd = imp_implementationWithBlock(^(id obj) { 3198*1b3f573fSAndroid Build Coastguard Worker return GPBGetHasIvar(obj, index, fieldNum); 3199*1b3f573fSAndroid Build Coastguard Worker }); 3200*1b3f573fSAndroid Build Coastguard Worker result.encodingSelector = @selector(getBool); 3201*1b3f573fSAndroid Build Coastguard Worker break; 3202*1b3f573fSAndroid Build Coastguard Worker } else if (sel == field->setHasSel_) { 3203*1b3f573fSAndroid Build Coastguard Worker result.impToAdd = imp_implementationWithBlock(^(id obj, BOOL value) { 3204*1b3f573fSAndroid Build Coastguard Worker if (value) { 3205*1b3f573fSAndroid Build Coastguard Worker [NSException raise:NSInvalidArgumentException 3206*1b3f573fSAndroid Build Coastguard Worker format:@"%@: %@ can only be set to NO (to clear field).", 3207*1b3f573fSAndroid Build Coastguard Worker [obj class], 3208*1b3f573fSAndroid Build Coastguard Worker NSStringFromSelector(field->setHasSel_)]; 3209*1b3f573fSAndroid Build Coastguard Worker } 3210*1b3f573fSAndroid Build Coastguard Worker GPBClearMessageField(obj, field); 3211*1b3f573fSAndroid Build Coastguard Worker }); 3212*1b3f573fSAndroid Build Coastguard Worker result.encodingSelector = @selector(setBool:); 3213*1b3f573fSAndroid Build Coastguard Worker break; 3214*1b3f573fSAndroid Build Coastguard Worker } else { 3215*1b3f573fSAndroid Build Coastguard Worker GPBOneofDescriptor *oneof = field->containingOneof_; 3216*1b3f573fSAndroid Build Coastguard Worker if (oneof && (sel == oneof->caseSel_)) { 3217*1b3f573fSAndroid Build Coastguard Worker int32_t index = GPBFieldHasIndex(field); 3218*1b3f573fSAndroid Build Coastguard Worker result.impToAdd = imp_implementationWithBlock(^(id obj) { 3219*1b3f573fSAndroid Build Coastguard Worker return GPBGetHasOneof(obj, index); 3220*1b3f573fSAndroid Build Coastguard Worker }); 3221*1b3f573fSAndroid Build Coastguard Worker result.encodingSelector = @selector(getEnum); 3222*1b3f573fSAndroid Build Coastguard Worker break; 3223*1b3f573fSAndroid Build Coastguard Worker } 3224*1b3f573fSAndroid Build Coastguard Worker } 3225*1b3f573fSAndroid Build Coastguard Worker } else { 3226*1b3f573fSAndroid Build Coastguard Worker // map<>/repeated fields. 3227*1b3f573fSAndroid Build Coastguard Worker if (sel == field->getSel_) { 3228*1b3f573fSAndroid Build Coastguard Worker if (field.fieldType == GPBFieldTypeRepeated) { 3229*1b3f573fSAndroid Build Coastguard Worker result.impToAdd = imp_implementationWithBlock(^(id obj) { 3230*1b3f573fSAndroid Build Coastguard Worker return GetArrayIvarWithField(obj, field); 3231*1b3f573fSAndroid Build Coastguard Worker }); 3232*1b3f573fSAndroid Build Coastguard Worker } else { 3233*1b3f573fSAndroid Build Coastguard Worker result.impToAdd = imp_implementationWithBlock(^(id obj) { 3234*1b3f573fSAndroid Build Coastguard Worker return GetMapIvarWithField(obj, field); 3235*1b3f573fSAndroid Build Coastguard Worker }); 3236*1b3f573fSAndroid Build Coastguard Worker } 3237*1b3f573fSAndroid Build Coastguard Worker result.encodingSelector = @selector(getArray); 3238*1b3f573fSAndroid Build Coastguard Worker break; 3239*1b3f573fSAndroid Build Coastguard Worker } else if (sel == field->setSel_) { 3240*1b3f573fSAndroid Build Coastguard Worker // Local for syntax so the block can directly capture it and not the 3241*1b3f573fSAndroid Build Coastguard Worker // full lookup. 3242*1b3f573fSAndroid Build Coastguard Worker result.impToAdd = imp_implementationWithBlock(^(id obj, id value) { 3243*1b3f573fSAndroid Build Coastguard Worker GPBSetObjectIvarWithFieldPrivate(obj, field, value); 3244*1b3f573fSAndroid Build Coastguard Worker }); 3245*1b3f573fSAndroid Build Coastguard Worker result.encodingSelector = @selector(setArray:); 3246*1b3f573fSAndroid Build Coastguard Worker break; 3247*1b3f573fSAndroid Build Coastguard Worker } else if (sel == field->hasOrCountSel_) { 3248*1b3f573fSAndroid Build Coastguard Worker result.impToAdd = imp_implementationWithBlock(^(id obj) { 3249*1b3f573fSAndroid Build Coastguard Worker // Type doesn't matter, all *Array and *Dictionary types support 3250*1b3f573fSAndroid Build Coastguard Worker // -count. 3251*1b3f573fSAndroid Build Coastguard Worker NSArray *arrayOrMap = 3252*1b3f573fSAndroid Build Coastguard Worker GPBGetObjectIvarWithFieldNoAutocreate(obj, field); 3253*1b3f573fSAndroid Build Coastguard Worker return [arrayOrMap count]; 3254*1b3f573fSAndroid Build Coastguard Worker }); 3255*1b3f573fSAndroid Build Coastguard Worker result.encodingSelector = @selector(getArrayCount); 3256*1b3f573fSAndroid Build Coastguard Worker break; 3257*1b3f573fSAndroid Build Coastguard Worker } 3258*1b3f573fSAndroid Build Coastguard Worker } 3259*1b3f573fSAndroid Build Coastguard Worker } 3260*1b3f573fSAndroid Build Coastguard Worker if (result.impToAdd) { 3261*1b3f573fSAndroid Build Coastguard Worker const char *encoding = 3262*1b3f573fSAndroid Build Coastguard Worker GPBMessageEncodingForSelector(result.encodingSelector, YES); 3263*1b3f573fSAndroid Build Coastguard Worker Class msgClass = descriptor.messageClass; 3264*1b3f573fSAndroid Build Coastguard Worker BOOL methodAdded = class_addMethod(msgClass, sel, result.impToAdd, encoding); 3265*1b3f573fSAndroid Build Coastguard Worker // class_addMethod() is documented as also failing if the method was already 3266*1b3f573fSAndroid Build Coastguard Worker // added; so we check if the method is already there and return success so 3267*1b3f573fSAndroid Build Coastguard Worker // the method dispatch will still happen. Why would it already be added? 3268*1b3f573fSAndroid Build Coastguard Worker // Two threads could cause the same method to be bound at the same time, 3269*1b3f573fSAndroid Build Coastguard Worker // but only one will actually bind it; the other still needs to return true 3270*1b3f573fSAndroid Build Coastguard Worker // so things will dispatch. 3271*1b3f573fSAndroid Build Coastguard Worker if (!methodAdded) { 3272*1b3f573fSAndroid Build Coastguard Worker methodAdded = GPBClassHasSel(msgClass, sel); 3273*1b3f573fSAndroid Build Coastguard Worker } 3274*1b3f573fSAndroid Build Coastguard Worker return methodAdded; 3275*1b3f573fSAndroid Build Coastguard Worker } 3276*1b3f573fSAndroid Build Coastguard Worker return [super resolveInstanceMethod:sel]; 3277*1b3f573fSAndroid Build Coastguard Worker} 3278*1b3f573fSAndroid Build Coastguard Worker 3279*1b3f573fSAndroid Build Coastguard Worker+ (BOOL)resolveClassMethod:(SEL)sel { 3280*1b3f573fSAndroid Build Coastguard Worker // Extensions scoped to a Message and looked up via class methods. 3281*1b3f573fSAndroid Build Coastguard Worker if (GPBResolveExtensionClassMethod(self, sel)) { 3282*1b3f573fSAndroid Build Coastguard Worker return YES; 3283*1b3f573fSAndroid Build Coastguard Worker } 3284*1b3f573fSAndroid Build Coastguard Worker return [super resolveClassMethod:sel]; 3285*1b3f573fSAndroid Build Coastguard Worker} 3286*1b3f573fSAndroid Build Coastguard Worker 3287*1b3f573fSAndroid Build Coastguard Worker#pragma mark - NSCoding Support 3288*1b3f573fSAndroid Build Coastguard Worker 3289*1b3f573fSAndroid Build Coastguard Worker+ (BOOL)supportsSecureCoding { 3290*1b3f573fSAndroid Build Coastguard Worker return YES; 3291*1b3f573fSAndroid Build Coastguard Worker} 3292*1b3f573fSAndroid Build Coastguard Worker 3293*1b3f573fSAndroid Build Coastguard Worker- (instancetype)initWithCoder:(NSCoder *)aDecoder { 3294*1b3f573fSAndroid Build Coastguard Worker self = [self init]; 3295*1b3f573fSAndroid Build Coastguard Worker if (self) { 3296*1b3f573fSAndroid Build Coastguard Worker NSData *data = 3297*1b3f573fSAndroid Build Coastguard Worker [aDecoder decodeObjectOfClass:[NSData class] forKey:kGPBDataCoderKey]; 3298*1b3f573fSAndroid Build Coastguard Worker if (data.length) { 3299*1b3f573fSAndroid Build Coastguard Worker [self mergeFromData:data extensionRegistry:nil]; 3300*1b3f573fSAndroid Build Coastguard Worker } 3301*1b3f573fSAndroid Build Coastguard Worker } 3302*1b3f573fSAndroid Build Coastguard Worker return self; 3303*1b3f573fSAndroid Build Coastguard Worker} 3304*1b3f573fSAndroid Build Coastguard Worker 3305*1b3f573fSAndroid Build Coastguard Worker- (void)encodeWithCoder:(NSCoder *)aCoder { 3306*1b3f573fSAndroid Build Coastguard Worker#if defined(DEBUG) && DEBUG 3307*1b3f573fSAndroid Build Coastguard Worker if (extensionMap_.count) { 3308*1b3f573fSAndroid Build Coastguard Worker // Hint to go along with the docs on GPBMessage about this. 3309*1b3f573fSAndroid Build Coastguard Worker // 3310*1b3f573fSAndroid Build Coastguard Worker // Note: This is incomplete, in that it only checked the "root" message, 3311*1b3f573fSAndroid Build Coastguard Worker // if a sub message in a field has extensions, the issue still exists. A 3312*1b3f573fSAndroid Build Coastguard Worker // recursive check could be done here (like the work in 3313*1b3f573fSAndroid Build Coastguard Worker // GPBMessageDropUnknownFieldsRecursively()), but that has the potential to 3314*1b3f573fSAndroid Build Coastguard Worker // be expensive and could slow down serialization in DEBUG enough to cause 3315*1b3f573fSAndroid Build Coastguard Worker // developers other problems. 3316*1b3f573fSAndroid Build Coastguard Worker NSLog(@"Warning: writing out a GPBMessage (%@) via NSCoding and it" 3317*1b3f573fSAndroid Build Coastguard Worker @" has %ld extensions; when read back in, those fields will be" 3318*1b3f573fSAndroid Build Coastguard Worker @" in the unknownFields property instead.", 3319*1b3f573fSAndroid Build Coastguard Worker [self class], (long)extensionMap_.count); 3320*1b3f573fSAndroid Build Coastguard Worker } 3321*1b3f573fSAndroid Build Coastguard Worker#endif 3322*1b3f573fSAndroid Build Coastguard Worker NSData *data = [self data]; 3323*1b3f573fSAndroid Build Coastguard Worker if (data.length) { 3324*1b3f573fSAndroid Build Coastguard Worker [aCoder encodeObject:data forKey:kGPBDataCoderKey]; 3325*1b3f573fSAndroid Build Coastguard Worker } 3326*1b3f573fSAndroid Build Coastguard Worker} 3327*1b3f573fSAndroid Build Coastguard Worker 3328*1b3f573fSAndroid Build Coastguard Worker#pragma mark - KVC Support 3329*1b3f573fSAndroid Build Coastguard Worker 3330*1b3f573fSAndroid Build Coastguard Worker+ (BOOL)accessInstanceVariablesDirectly { 3331*1b3f573fSAndroid Build Coastguard Worker // Make sure KVC doesn't use instance variables. 3332*1b3f573fSAndroid Build Coastguard Worker return NO; 3333*1b3f573fSAndroid Build Coastguard Worker} 3334*1b3f573fSAndroid Build Coastguard Worker 3335*1b3f573fSAndroid Build Coastguard Worker@end 3336*1b3f573fSAndroid Build Coastguard Worker 3337*1b3f573fSAndroid Build Coastguard Worker#pragma mark - Messages from GPBUtilities.h but defined here for access to helpers. 3338*1b3f573fSAndroid Build Coastguard Worker 3339*1b3f573fSAndroid Build Coastguard Worker// Only exists for public api, no core code should use this. 3340*1b3f573fSAndroid Build Coastguard Workerid GPBGetMessageRepeatedField(GPBMessage *self, GPBFieldDescriptor *field) { 3341*1b3f573fSAndroid Build Coastguard Worker#if defined(DEBUG) && DEBUG 3342*1b3f573fSAndroid Build Coastguard Worker if (field.fieldType != GPBFieldTypeRepeated) { 3343*1b3f573fSAndroid Build Coastguard Worker [NSException raise:NSInvalidArgumentException 3344*1b3f573fSAndroid Build Coastguard Worker format:@"%@.%@ is not a repeated field.", 3345*1b3f573fSAndroid Build Coastguard Worker [self class], field.name]; 3346*1b3f573fSAndroid Build Coastguard Worker } 3347*1b3f573fSAndroid Build Coastguard Worker#endif 3348*1b3f573fSAndroid Build Coastguard Worker return GetOrCreateArrayIvarWithField(self, field); 3349*1b3f573fSAndroid Build Coastguard Worker} 3350*1b3f573fSAndroid Build Coastguard Worker 3351*1b3f573fSAndroid Build Coastguard Worker// Only exists for public api, no core code should use this. 3352*1b3f573fSAndroid Build Coastguard Workerid GPBGetMessageMapField(GPBMessage *self, GPBFieldDescriptor *field) { 3353*1b3f573fSAndroid Build Coastguard Worker#if defined(DEBUG) && DEBUG 3354*1b3f573fSAndroid Build Coastguard Worker if (field.fieldType != GPBFieldTypeMap) { 3355*1b3f573fSAndroid Build Coastguard Worker [NSException raise:NSInvalidArgumentException 3356*1b3f573fSAndroid Build Coastguard Worker format:@"%@.%@ is not a map<> field.", 3357*1b3f573fSAndroid Build Coastguard Worker [self class], field.name]; 3358*1b3f573fSAndroid Build Coastguard Worker } 3359*1b3f573fSAndroid Build Coastguard Worker#endif 3360*1b3f573fSAndroid Build Coastguard Worker return GetOrCreateMapIvarWithField(self, field); 3361*1b3f573fSAndroid Build Coastguard Worker} 3362*1b3f573fSAndroid Build Coastguard Worker 3363*1b3f573fSAndroid Build Coastguard Workerid GPBGetObjectIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) { 3364*1b3f573fSAndroid Build Coastguard Worker NSCAssert(!GPBFieldIsMapOrArray(field), @"Shouldn't get here"); 3365*1b3f573fSAndroid Build Coastguard Worker if (!GPBFieldDataTypeIsMessage(field)) { 3366*1b3f573fSAndroid Build Coastguard Worker if (GPBGetHasIvarField(self, field)) { 3367*1b3f573fSAndroid Build Coastguard Worker uint8_t *storage = (uint8_t *)self->messageStorage_; 3368*1b3f573fSAndroid Build Coastguard Worker id *typePtr = (id *)&storage[field->description_->offset]; 3369*1b3f573fSAndroid Build Coastguard Worker return *typePtr; 3370*1b3f573fSAndroid Build Coastguard Worker } 3371*1b3f573fSAndroid Build Coastguard Worker // Not set...non messages (string/data), get their default. 3372*1b3f573fSAndroid Build Coastguard Worker return field.defaultValue.valueMessage; 3373*1b3f573fSAndroid Build Coastguard Worker } 3374*1b3f573fSAndroid Build Coastguard Worker 3375*1b3f573fSAndroid Build Coastguard Worker uint8_t *storage = (uint8_t *)self->messageStorage_; 3376*1b3f573fSAndroid Build Coastguard Worker _Atomic(id) *typePtr = (_Atomic(id) *)&storage[field->description_->offset]; 3377*1b3f573fSAndroid Build Coastguard Worker id msg = atomic_load(typePtr); 3378*1b3f573fSAndroid Build Coastguard Worker if (msg) { 3379*1b3f573fSAndroid Build Coastguard Worker return msg; 3380*1b3f573fSAndroid Build Coastguard Worker } 3381*1b3f573fSAndroid Build Coastguard Worker 3382*1b3f573fSAndroid Build Coastguard Worker id expected = nil; 3383*1b3f573fSAndroid Build Coastguard Worker id autocreated = GPBCreateMessageWithAutocreator(field.msgClass, self, field); 3384*1b3f573fSAndroid Build Coastguard Worker if (atomic_compare_exchange_strong(typePtr, &expected, autocreated)) { 3385*1b3f573fSAndroid Build Coastguard Worker // Value was set, return it. 3386*1b3f573fSAndroid Build Coastguard Worker return autocreated; 3387*1b3f573fSAndroid Build Coastguard Worker } 3388*1b3f573fSAndroid Build Coastguard Worker 3389*1b3f573fSAndroid Build Coastguard Worker // Some other thread set it, release the one created and return what got set. 3390*1b3f573fSAndroid Build Coastguard Worker GPBClearMessageAutocreator(autocreated); 3391*1b3f573fSAndroid Build Coastguard Worker [autocreated release]; 3392*1b3f573fSAndroid Build Coastguard Worker return expected; 3393*1b3f573fSAndroid Build Coastguard Worker} 3394*1b3f573fSAndroid Build Coastguard Worker 3395*1b3f573fSAndroid Build Coastguard Worker#pragma clang diagnostic pop 3396