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