1*6777b538SAndroid Build Coastguard Worker// Protocol Buffers - Google's data interchange format 2*6777b538SAndroid Build Coastguard Worker// Copyright 2008 Google Inc. All rights reserved. 3*6777b538SAndroid Build Coastguard Worker// https://developers.google.com/protocol-buffers/ 4*6777b538SAndroid Build Coastguard Worker// 5*6777b538SAndroid Build Coastguard Worker// Redistribution and use in source and binary forms, with or without 6*6777b538SAndroid Build Coastguard Worker// modification, are permitted provided that the following conditions are 7*6777b538SAndroid Build Coastguard Worker// met: 8*6777b538SAndroid Build Coastguard Worker// 9*6777b538SAndroid Build Coastguard Worker// * Redistributions of source code must retain the above copyright 10*6777b538SAndroid Build Coastguard Worker// notice, this list of conditions and the following disclaimer. 11*6777b538SAndroid Build Coastguard Worker// * Redistributions in binary form must reproduce the above 12*6777b538SAndroid Build Coastguard Worker// copyright notice, this list of conditions and the following disclaimer 13*6777b538SAndroid Build Coastguard Worker// in the documentation and/or other materials provided with the 14*6777b538SAndroid Build Coastguard Worker// distribution. 15*6777b538SAndroid Build Coastguard Worker// * Neither the name of Google Inc. nor the names of its 16*6777b538SAndroid Build Coastguard Worker// contributors may be used to endorse or promote products derived from 17*6777b538SAndroid Build Coastguard Worker// this software without specific prior written permission. 18*6777b538SAndroid Build Coastguard Worker// 19*6777b538SAndroid Build Coastguard Worker// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20*6777b538SAndroid Build Coastguard Worker// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21*6777b538SAndroid Build Coastguard Worker// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22*6777b538SAndroid Build Coastguard Worker// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23*6777b538SAndroid Build Coastguard Worker// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24*6777b538SAndroid Build Coastguard Worker// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25*6777b538SAndroid Build Coastguard Worker// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26*6777b538SAndroid Build Coastguard Worker// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27*6777b538SAndroid Build Coastguard Worker// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28*6777b538SAndroid Build Coastguard Worker// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29*6777b538SAndroid Build Coastguard Worker// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30*6777b538SAndroid Build Coastguard Worker 31*6777b538SAndroid Build Coastguard Worker#import "GPBUnknownFieldSet_PackagePrivate.h" 32*6777b538SAndroid Build Coastguard Worker 33*6777b538SAndroid Build Coastguard Worker#import "GPBCodedInputStream_PackagePrivate.h" 34*6777b538SAndroid Build Coastguard Worker#import "GPBCodedOutputStream.h" 35*6777b538SAndroid Build Coastguard Worker#import "GPBUnknownField_PackagePrivate.h" 36*6777b538SAndroid Build Coastguard Worker#import "GPBUtilities.h" 37*6777b538SAndroid Build Coastguard Worker#import "GPBWireFormat.h" 38*6777b538SAndroid Build Coastguard Worker 39*6777b538SAndroid Build Coastguard Worker#pragma mark Helpers 40*6777b538SAndroid Build Coastguard Worker 41*6777b538SAndroid Build Coastguard Workerstatic void checkNumber(int32_t number) { 42*6777b538SAndroid Build Coastguard Worker if (number == 0) { 43*6777b538SAndroid Build Coastguard Worker [NSException raise:NSInvalidArgumentException 44*6777b538SAndroid Build Coastguard Worker format:@"Zero is not a valid field number."]; 45*6777b538SAndroid Build Coastguard Worker } 46*6777b538SAndroid Build Coastguard Worker} 47*6777b538SAndroid Build Coastguard Worker 48*6777b538SAndroid Build Coastguard Worker@implementation GPBUnknownFieldSet { 49*6777b538SAndroid Build Coastguard Worker @package 50*6777b538SAndroid Build Coastguard Worker CFMutableDictionaryRef fields_; 51*6777b538SAndroid Build Coastguard Worker} 52*6777b538SAndroid Build Coastguard Worker 53*6777b538SAndroid Build Coastguard Workerstatic void CopyWorker(const void *key, const void *value, void *context) { 54*6777b538SAndroid Build Coastguard Worker#pragma unused(key) 55*6777b538SAndroid Build Coastguard Worker GPBUnknownField *field = value; 56*6777b538SAndroid Build Coastguard Worker GPBUnknownFieldSet *result = context; 57*6777b538SAndroid Build Coastguard Worker 58*6777b538SAndroid Build Coastguard Worker GPBUnknownField *copied = [field copy]; 59*6777b538SAndroid Build Coastguard Worker [result addField:copied]; 60*6777b538SAndroid Build Coastguard Worker [copied release]; 61*6777b538SAndroid Build Coastguard Worker} 62*6777b538SAndroid Build Coastguard Worker 63*6777b538SAndroid Build Coastguard Worker// Direct access is use for speed, to avoid even internally declaring things 64*6777b538SAndroid Build Coastguard Worker// read/write, etc. The warning is enabled in the project to ensure code calling 65*6777b538SAndroid Build Coastguard Worker// protos can turn on -Wdirect-ivar-access without issues. 66*6777b538SAndroid Build Coastguard Worker#pragma clang diagnostic push 67*6777b538SAndroid Build Coastguard Worker#pragma clang diagnostic ignored "-Wdirect-ivar-access" 68*6777b538SAndroid Build Coastguard Worker 69*6777b538SAndroid Build Coastguard Worker- (id)copyWithZone:(NSZone *)zone { 70*6777b538SAndroid Build Coastguard Worker GPBUnknownFieldSet *result = [[GPBUnknownFieldSet allocWithZone:zone] init]; 71*6777b538SAndroid Build Coastguard Worker if (fields_) { 72*6777b538SAndroid Build Coastguard Worker CFDictionaryApplyFunction(fields_, CopyWorker, result); 73*6777b538SAndroid Build Coastguard Worker } 74*6777b538SAndroid Build Coastguard Worker return result; 75*6777b538SAndroid Build Coastguard Worker} 76*6777b538SAndroid Build Coastguard Worker 77*6777b538SAndroid Build Coastguard Worker- (void)dealloc { 78*6777b538SAndroid Build Coastguard Worker if (fields_) { 79*6777b538SAndroid Build Coastguard Worker CFRelease(fields_); 80*6777b538SAndroid Build Coastguard Worker } 81*6777b538SAndroid Build Coastguard Worker [super dealloc]; 82*6777b538SAndroid Build Coastguard Worker} 83*6777b538SAndroid Build Coastguard Worker 84*6777b538SAndroid Build Coastguard Worker- (BOOL)isEqual:(id)object { 85*6777b538SAndroid Build Coastguard Worker BOOL equal = NO; 86*6777b538SAndroid Build Coastguard Worker if ([object isKindOfClass:[GPBUnknownFieldSet class]]) { 87*6777b538SAndroid Build Coastguard Worker GPBUnknownFieldSet *set = (GPBUnknownFieldSet *)object; 88*6777b538SAndroid Build Coastguard Worker if ((fields_ == NULL) && (set->fields_ == NULL)) { 89*6777b538SAndroid Build Coastguard Worker equal = YES; 90*6777b538SAndroid Build Coastguard Worker } else if ((fields_ != NULL) && (set->fields_ != NULL)) { 91*6777b538SAndroid Build Coastguard Worker equal = CFEqual(fields_, set->fields_); 92*6777b538SAndroid Build Coastguard Worker } 93*6777b538SAndroid Build Coastguard Worker } 94*6777b538SAndroid Build Coastguard Worker return equal; 95*6777b538SAndroid Build Coastguard Worker} 96*6777b538SAndroid Build Coastguard Worker 97*6777b538SAndroid Build Coastguard Worker- (NSUInteger)hash { 98*6777b538SAndroid Build Coastguard Worker // Return the hash of the fields dictionary (or just some value). 99*6777b538SAndroid Build Coastguard Worker if (fields_) { 100*6777b538SAndroid Build Coastguard Worker return CFHash(fields_); 101*6777b538SAndroid Build Coastguard Worker } 102*6777b538SAndroid Build Coastguard Worker return (NSUInteger)[GPBUnknownFieldSet class]; 103*6777b538SAndroid Build Coastguard Worker} 104*6777b538SAndroid Build Coastguard Worker 105*6777b538SAndroid Build Coastguard Worker#pragma mark - Public Methods 106*6777b538SAndroid Build Coastguard Worker 107*6777b538SAndroid Build Coastguard Worker- (BOOL)hasField:(int32_t)number { 108*6777b538SAndroid Build Coastguard Worker ssize_t key = number; 109*6777b538SAndroid Build Coastguard Worker return fields_ ? (CFDictionaryGetValue(fields_, (void *)key) != nil) : NO; 110*6777b538SAndroid Build Coastguard Worker} 111*6777b538SAndroid Build Coastguard Worker 112*6777b538SAndroid Build Coastguard Worker- (GPBUnknownField *)getField:(int32_t)number { 113*6777b538SAndroid Build Coastguard Worker ssize_t key = number; 114*6777b538SAndroid Build Coastguard Worker GPBUnknownField *result = 115*6777b538SAndroid Build Coastguard Worker fields_ ? CFDictionaryGetValue(fields_, (void *)key) : nil; 116*6777b538SAndroid Build Coastguard Worker return result; 117*6777b538SAndroid Build Coastguard Worker} 118*6777b538SAndroid Build Coastguard Worker 119*6777b538SAndroid Build Coastguard Worker- (NSUInteger)countOfFields { 120*6777b538SAndroid Build Coastguard Worker return fields_ ? CFDictionaryGetCount(fields_) : 0; 121*6777b538SAndroid Build Coastguard Worker} 122*6777b538SAndroid Build Coastguard Worker 123*6777b538SAndroid Build Coastguard Worker- (NSArray *)sortedFields { 124*6777b538SAndroid Build Coastguard Worker if (!fields_) return [NSArray array]; 125*6777b538SAndroid Build Coastguard Worker size_t count = CFDictionaryGetCount(fields_); 126*6777b538SAndroid Build Coastguard Worker ssize_t keys[count]; 127*6777b538SAndroid Build Coastguard Worker GPBUnknownField *values[count]; 128*6777b538SAndroid Build Coastguard Worker CFDictionaryGetKeysAndValues(fields_, (const void **)keys, 129*6777b538SAndroid Build Coastguard Worker (const void **)values); 130*6777b538SAndroid Build Coastguard Worker struct GPBFieldPair { 131*6777b538SAndroid Build Coastguard Worker ssize_t key; 132*6777b538SAndroid Build Coastguard Worker GPBUnknownField *value; 133*6777b538SAndroid Build Coastguard Worker } pairs[count]; 134*6777b538SAndroid Build Coastguard Worker for (size_t i = 0; i < count; ++i) { 135*6777b538SAndroid Build Coastguard Worker pairs[i].key = keys[i]; 136*6777b538SAndroid Build Coastguard Worker pairs[i].value = values[i]; 137*6777b538SAndroid Build Coastguard Worker }; 138*6777b538SAndroid Build Coastguard Worker qsort_b(pairs, count, sizeof(struct GPBFieldPair), 139*6777b538SAndroid Build Coastguard Worker ^(const void *first, const void *second) { 140*6777b538SAndroid Build Coastguard Worker const struct GPBFieldPair *a = first; 141*6777b538SAndroid Build Coastguard Worker const struct GPBFieldPair *b = second; 142*6777b538SAndroid Build Coastguard Worker return (a->key > b->key) ? 1 : ((a->key == b->key) ? 0 : -1); 143*6777b538SAndroid Build Coastguard Worker }); 144*6777b538SAndroid Build Coastguard Worker for (size_t i = 0; i < count; ++i) { 145*6777b538SAndroid Build Coastguard Worker values[i] = pairs[i].value; 146*6777b538SAndroid Build Coastguard Worker }; 147*6777b538SAndroid Build Coastguard Worker return [NSArray arrayWithObjects:values count:count]; 148*6777b538SAndroid Build Coastguard Worker} 149*6777b538SAndroid Build Coastguard Worker 150*6777b538SAndroid Build Coastguard Worker#pragma mark - Internal Methods 151*6777b538SAndroid Build Coastguard Worker 152*6777b538SAndroid Build Coastguard Worker- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)output { 153*6777b538SAndroid Build Coastguard Worker if (!fields_) return; 154*6777b538SAndroid Build Coastguard Worker size_t count = CFDictionaryGetCount(fields_); 155*6777b538SAndroid Build Coastguard Worker ssize_t keys[count]; 156*6777b538SAndroid Build Coastguard Worker GPBUnknownField *values[count]; 157*6777b538SAndroid Build Coastguard Worker CFDictionaryGetKeysAndValues(fields_, (const void **)keys, 158*6777b538SAndroid Build Coastguard Worker (const void **)values); 159*6777b538SAndroid Build Coastguard Worker if (count > 1) { 160*6777b538SAndroid Build Coastguard Worker struct GPBFieldPair { 161*6777b538SAndroid Build Coastguard Worker ssize_t key; 162*6777b538SAndroid Build Coastguard Worker GPBUnknownField *value; 163*6777b538SAndroid Build Coastguard Worker } pairs[count]; 164*6777b538SAndroid Build Coastguard Worker 165*6777b538SAndroid Build Coastguard Worker for (size_t i = 0; i < count; ++i) { 166*6777b538SAndroid Build Coastguard Worker pairs[i].key = keys[i]; 167*6777b538SAndroid Build Coastguard Worker pairs[i].value = values[i]; 168*6777b538SAndroid Build Coastguard Worker }; 169*6777b538SAndroid Build Coastguard Worker qsort_b(pairs, count, sizeof(struct GPBFieldPair), 170*6777b538SAndroid Build Coastguard Worker ^(const void *first, const void *second) { 171*6777b538SAndroid Build Coastguard Worker const struct GPBFieldPair *a = first; 172*6777b538SAndroid Build Coastguard Worker const struct GPBFieldPair *b = second; 173*6777b538SAndroid Build Coastguard Worker return (a->key > b->key) ? 1 : ((a->key == b->key) ? 0 : -1); 174*6777b538SAndroid Build Coastguard Worker }); 175*6777b538SAndroid Build Coastguard Worker for (size_t i = 0; i < count; ++i) { 176*6777b538SAndroid Build Coastguard Worker GPBUnknownField *value = pairs[i].value; 177*6777b538SAndroid Build Coastguard Worker [value writeToOutput:output]; 178*6777b538SAndroid Build Coastguard Worker } 179*6777b538SAndroid Build Coastguard Worker } else { 180*6777b538SAndroid Build Coastguard Worker [values[0] writeToOutput:output]; 181*6777b538SAndroid Build Coastguard Worker } 182*6777b538SAndroid Build Coastguard Worker} 183*6777b538SAndroid Build Coastguard Worker 184*6777b538SAndroid Build Coastguard Worker- (NSString *)description { 185*6777b538SAndroid Build Coastguard Worker NSMutableString *description = [NSMutableString 186*6777b538SAndroid Build Coastguard Worker stringWithFormat:@"<%@ %p>: TextFormat: {\n", [self class], self]; 187*6777b538SAndroid Build Coastguard Worker NSString *textFormat = GPBTextFormatForUnknownFieldSet(self, @" "); 188*6777b538SAndroid Build Coastguard Worker [description appendString:textFormat]; 189*6777b538SAndroid Build Coastguard Worker [description appendString:@"}"]; 190*6777b538SAndroid Build Coastguard Worker return description; 191*6777b538SAndroid Build Coastguard Worker} 192*6777b538SAndroid Build Coastguard Worker 193*6777b538SAndroid Build Coastguard Workerstatic void GPBUnknownFieldSetSerializedSize(const void *key, const void *value, 194*6777b538SAndroid Build Coastguard Worker void *context) { 195*6777b538SAndroid Build Coastguard Worker#pragma unused(key) 196*6777b538SAndroid Build Coastguard Worker GPBUnknownField *field = value; 197*6777b538SAndroid Build Coastguard Worker size_t *result = context; 198*6777b538SAndroid Build Coastguard Worker *result += [field serializedSize]; 199*6777b538SAndroid Build Coastguard Worker} 200*6777b538SAndroid Build Coastguard Worker 201*6777b538SAndroid Build Coastguard Worker- (size_t)serializedSize { 202*6777b538SAndroid Build Coastguard Worker size_t result = 0; 203*6777b538SAndroid Build Coastguard Worker if (fields_) { 204*6777b538SAndroid Build Coastguard Worker CFDictionaryApplyFunction(fields_, GPBUnknownFieldSetSerializedSize, 205*6777b538SAndroid Build Coastguard Worker &result); 206*6777b538SAndroid Build Coastguard Worker } 207*6777b538SAndroid Build Coastguard Worker return result; 208*6777b538SAndroid Build Coastguard Worker} 209*6777b538SAndroid Build Coastguard Worker 210*6777b538SAndroid Build Coastguard Workerstatic void GPBUnknownFieldSetWriteAsMessageSetTo(const void *key, 211*6777b538SAndroid Build Coastguard Worker const void *value, 212*6777b538SAndroid Build Coastguard Worker void *context) { 213*6777b538SAndroid Build Coastguard Worker#pragma unused(key) 214*6777b538SAndroid Build Coastguard Worker GPBUnknownField *field = value; 215*6777b538SAndroid Build Coastguard Worker GPBCodedOutputStream *output = context; 216*6777b538SAndroid Build Coastguard Worker [field writeAsMessageSetExtensionToOutput:output]; 217*6777b538SAndroid Build Coastguard Worker} 218*6777b538SAndroid Build Coastguard Worker 219*6777b538SAndroid Build Coastguard Worker- (void)writeAsMessageSetTo:(GPBCodedOutputStream *)output { 220*6777b538SAndroid Build Coastguard Worker if (fields_) { 221*6777b538SAndroid Build Coastguard Worker CFDictionaryApplyFunction(fields_, GPBUnknownFieldSetWriteAsMessageSetTo, 222*6777b538SAndroid Build Coastguard Worker output); 223*6777b538SAndroid Build Coastguard Worker } 224*6777b538SAndroid Build Coastguard Worker} 225*6777b538SAndroid Build Coastguard Worker 226*6777b538SAndroid Build Coastguard Workerstatic void GPBUnknownFieldSetSerializedSizeAsMessageSet(const void *key, 227*6777b538SAndroid Build Coastguard Worker const void *value, 228*6777b538SAndroid Build Coastguard Worker void *context) { 229*6777b538SAndroid Build Coastguard Worker#pragma unused(key) 230*6777b538SAndroid Build Coastguard Worker GPBUnknownField *field = value; 231*6777b538SAndroid Build Coastguard Worker size_t *result = context; 232*6777b538SAndroid Build Coastguard Worker *result += [field serializedSizeAsMessageSetExtension]; 233*6777b538SAndroid Build Coastguard Worker} 234*6777b538SAndroid Build Coastguard Worker 235*6777b538SAndroid Build Coastguard Worker- (size_t)serializedSizeAsMessageSet { 236*6777b538SAndroid Build Coastguard Worker size_t result = 0; 237*6777b538SAndroid Build Coastguard Worker if (fields_) { 238*6777b538SAndroid Build Coastguard Worker CFDictionaryApplyFunction( 239*6777b538SAndroid Build Coastguard Worker fields_, GPBUnknownFieldSetSerializedSizeAsMessageSet, &result); 240*6777b538SAndroid Build Coastguard Worker } 241*6777b538SAndroid Build Coastguard Worker return result; 242*6777b538SAndroid Build Coastguard Worker} 243*6777b538SAndroid Build Coastguard Worker 244*6777b538SAndroid Build Coastguard Worker- (NSData *)data { 245*6777b538SAndroid Build Coastguard Worker NSMutableData *data = [NSMutableData dataWithLength:self.serializedSize]; 246*6777b538SAndroid Build Coastguard Worker GPBCodedOutputStream *output = 247*6777b538SAndroid Build Coastguard Worker [[GPBCodedOutputStream alloc] initWithData:data]; 248*6777b538SAndroid Build Coastguard Worker [self writeToCodedOutputStream:output]; 249*6777b538SAndroid Build Coastguard Worker [output release]; 250*6777b538SAndroid Build Coastguard Worker return data; 251*6777b538SAndroid Build Coastguard Worker} 252*6777b538SAndroid Build Coastguard Worker 253*6777b538SAndroid Build Coastguard Worker+ (BOOL)isFieldTag:(int32_t)tag { 254*6777b538SAndroid Build Coastguard Worker return GPBWireFormatGetTagWireType(tag) != GPBWireFormatEndGroup; 255*6777b538SAndroid Build Coastguard Worker} 256*6777b538SAndroid Build Coastguard Worker 257*6777b538SAndroid Build Coastguard Worker- (void)addField:(GPBUnknownField *)field { 258*6777b538SAndroid Build Coastguard Worker int32_t number = [field number]; 259*6777b538SAndroid Build Coastguard Worker checkNumber(number); 260*6777b538SAndroid Build Coastguard Worker if (!fields_) { 261*6777b538SAndroid Build Coastguard Worker // Use a custom dictionary here because the keys are numbers and conversion 262*6777b538SAndroid Build Coastguard Worker // back and forth from NSNumber isn't worth the cost. 263*6777b538SAndroid Build Coastguard Worker fields_ = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, NULL, 264*6777b538SAndroid Build Coastguard Worker &kCFTypeDictionaryValueCallBacks); 265*6777b538SAndroid Build Coastguard Worker } 266*6777b538SAndroid Build Coastguard Worker ssize_t key = number; 267*6777b538SAndroid Build Coastguard Worker CFDictionarySetValue(fields_, (const void *)key, field); 268*6777b538SAndroid Build Coastguard Worker} 269*6777b538SAndroid Build Coastguard Worker 270*6777b538SAndroid Build Coastguard Worker- (GPBUnknownField *)mutableFieldForNumber:(int32_t)number create:(BOOL)create { 271*6777b538SAndroid Build Coastguard Worker ssize_t key = number; 272*6777b538SAndroid Build Coastguard Worker GPBUnknownField *existing = 273*6777b538SAndroid Build Coastguard Worker fields_ ? CFDictionaryGetValue(fields_, (const void *)key) : nil; 274*6777b538SAndroid Build Coastguard Worker if (!existing && create) { 275*6777b538SAndroid Build Coastguard Worker existing = [[GPBUnknownField alloc] initWithNumber:number]; 276*6777b538SAndroid Build Coastguard Worker // This retains existing. 277*6777b538SAndroid Build Coastguard Worker [self addField:existing]; 278*6777b538SAndroid Build Coastguard Worker [existing release]; 279*6777b538SAndroid Build Coastguard Worker } 280*6777b538SAndroid Build Coastguard Worker return existing; 281*6777b538SAndroid Build Coastguard Worker} 282*6777b538SAndroid Build Coastguard Worker 283*6777b538SAndroid Build Coastguard Workerstatic void GPBUnknownFieldSetMergeUnknownFields(const void *key, 284*6777b538SAndroid Build Coastguard Worker const void *value, 285*6777b538SAndroid Build Coastguard Worker void *context) { 286*6777b538SAndroid Build Coastguard Worker#pragma unused(key) 287*6777b538SAndroid Build Coastguard Worker GPBUnknownField *field = value; 288*6777b538SAndroid Build Coastguard Worker GPBUnknownFieldSet *self = context; 289*6777b538SAndroid Build Coastguard Worker 290*6777b538SAndroid Build Coastguard Worker int32_t number = [field number]; 291*6777b538SAndroid Build Coastguard Worker checkNumber(number); 292*6777b538SAndroid Build Coastguard Worker GPBUnknownField *oldField = [self mutableFieldForNumber:number create:NO]; 293*6777b538SAndroid Build Coastguard Worker if (oldField) { 294*6777b538SAndroid Build Coastguard Worker [oldField mergeFromField:field]; 295*6777b538SAndroid Build Coastguard Worker } else { 296*6777b538SAndroid Build Coastguard Worker // Merge only comes from GPBMessage's mergeFrom:, so it means we are on 297*6777b538SAndroid Build Coastguard Worker // mutable message and are an mutable instance, so make sure we need 298*6777b538SAndroid Build Coastguard Worker // mutable fields. 299*6777b538SAndroid Build Coastguard Worker GPBUnknownField *fieldCopy = [field copy]; 300*6777b538SAndroid Build Coastguard Worker [self addField:fieldCopy]; 301*6777b538SAndroid Build Coastguard Worker [fieldCopy release]; 302*6777b538SAndroid Build Coastguard Worker } 303*6777b538SAndroid Build Coastguard Worker} 304*6777b538SAndroid Build Coastguard Worker 305*6777b538SAndroid Build Coastguard Worker- (void)mergeUnknownFields:(GPBUnknownFieldSet *)other { 306*6777b538SAndroid Build Coastguard Worker if (other && other->fields_) { 307*6777b538SAndroid Build Coastguard Worker CFDictionaryApplyFunction(other->fields_, 308*6777b538SAndroid Build Coastguard Worker GPBUnknownFieldSetMergeUnknownFields, self); 309*6777b538SAndroid Build Coastguard Worker } 310*6777b538SAndroid Build Coastguard Worker} 311*6777b538SAndroid Build Coastguard Worker 312*6777b538SAndroid Build Coastguard Worker- (void)mergeFromData:(NSData *)data { 313*6777b538SAndroid Build Coastguard Worker GPBCodedInputStream *input = [[GPBCodedInputStream alloc] initWithData:data]; 314*6777b538SAndroid Build Coastguard Worker [self mergeFromCodedInputStream:input]; 315*6777b538SAndroid Build Coastguard Worker [input checkLastTagWas:0]; 316*6777b538SAndroid Build Coastguard Worker [input release]; 317*6777b538SAndroid Build Coastguard Worker} 318*6777b538SAndroid Build Coastguard Worker 319*6777b538SAndroid Build Coastguard Worker- (void)mergeVarintField:(int32_t)number value:(int32_t)value { 320*6777b538SAndroid Build Coastguard Worker checkNumber(number); 321*6777b538SAndroid Build Coastguard Worker [[self mutableFieldForNumber:number create:YES] addVarint:value]; 322*6777b538SAndroid Build Coastguard Worker} 323*6777b538SAndroid Build Coastguard Worker 324*6777b538SAndroid Build Coastguard Worker- (BOOL)mergeFieldFrom:(int32_t)tag input:(GPBCodedInputStream *)input { 325*6777b538SAndroid Build Coastguard Worker NSAssert(GPBWireFormatIsValidTag(tag), @"Got passed an invalid tag"); 326*6777b538SAndroid Build Coastguard Worker int32_t number = GPBWireFormatGetTagFieldNumber(tag); 327*6777b538SAndroid Build Coastguard Worker GPBCodedInputStreamState *state = &input->state_; 328*6777b538SAndroid Build Coastguard Worker switch (GPBWireFormatGetTagWireType(tag)) { 329*6777b538SAndroid Build Coastguard Worker case GPBWireFormatVarint: { 330*6777b538SAndroid Build Coastguard Worker GPBUnknownField *field = [self mutableFieldForNumber:number create:YES]; 331*6777b538SAndroid Build Coastguard Worker [field addVarint:GPBCodedInputStreamReadInt64(state)]; 332*6777b538SAndroid Build Coastguard Worker return YES; 333*6777b538SAndroid Build Coastguard Worker } 334*6777b538SAndroid Build Coastguard Worker case GPBWireFormatFixed64: { 335*6777b538SAndroid Build Coastguard Worker GPBUnknownField *field = [self mutableFieldForNumber:number create:YES]; 336*6777b538SAndroid Build Coastguard Worker [field addFixed64:GPBCodedInputStreamReadFixed64(state)]; 337*6777b538SAndroid Build Coastguard Worker return YES; 338*6777b538SAndroid Build Coastguard Worker } 339*6777b538SAndroid Build Coastguard Worker case GPBWireFormatLengthDelimited: { 340*6777b538SAndroid Build Coastguard Worker NSData *data = GPBCodedInputStreamReadRetainedBytes(state); 341*6777b538SAndroid Build Coastguard Worker GPBUnknownField *field = [self mutableFieldForNumber:number create:YES]; 342*6777b538SAndroid Build Coastguard Worker [field addLengthDelimited:data]; 343*6777b538SAndroid Build Coastguard Worker [data release]; 344*6777b538SAndroid Build Coastguard Worker return YES; 345*6777b538SAndroid Build Coastguard Worker } 346*6777b538SAndroid Build Coastguard Worker case GPBWireFormatStartGroup: { 347*6777b538SAndroid Build Coastguard Worker GPBUnknownFieldSet *unknownFieldSet = [[GPBUnknownFieldSet alloc] init]; 348*6777b538SAndroid Build Coastguard Worker [input readUnknownGroup:number message:unknownFieldSet]; 349*6777b538SAndroid Build Coastguard Worker GPBUnknownField *field = [self mutableFieldForNumber:number create:YES]; 350*6777b538SAndroid Build Coastguard Worker [field addGroup:unknownFieldSet]; 351*6777b538SAndroid Build Coastguard Worker [unknownFieldSet release]; 352*6777b538SAndroid Build Coastguard Worker return YES; 353*6777b538SAndroid Build Coastguard Worker } 354*6777b538SAndroid Build Coastguard Worker case GPBWireFormatEndGroup: 355*6777b538SAndroid Build Coastguard Worker return NO; 356*6777b538SAndroid Build Coastguard Worker case GPBWireFormatFixed32: { 357*6777b538SAndroid Build Coastguard Worker GPBUnknownField *field = [self mutableFieldForNumber:number create:YES]; 358*6777b538SAndroid Build Coastguard Worker [field addFixed32:GPBCodedInputStreamReadFixed32(state)]; 359*6777b538SAndroid Build Coastguard Worker return YES; 360*6777b538SAndroid Build Coastguard Worker } 361*6777b538SAndroid Build Coastguard Worker } 362*6777b538SAndroid Build Coastguard Worker} 363*6777b538SAndroid Build Coastguard Worker 364*6777b538SAndroid Build Coastguard Worker- (void)mergeMessageSetMessage:(int32_t)number data:(NSData *)messageData { 365*6777b538SAndroid Build Coastguard Worker [[self mutableFieldForNumber:number create:YES] 366*6777b538SAndroid Build Coastguard Worker addLengthDelimited:messageData]; 367*6777b538SAndroid Build Coastguard Worker} 368*6777b538SAndroid Build Coastguard Worker 369*6777b538SAndroid Build Coastguard Worker- (void)addUnknownMapEntry:(int32_t)fieldNum value:(NSData *)data { 370*6777b538SAndroid Build Coastguard Worker GPBUnknownField *field = [self mutableFieldForNumber:fieldNum create:YES]; 371*6777b538SAndroid Build Coastguard Worker [field addLengthDelimited:data]; 372*6777b538SAndroid Build Coastguard Worker} 373*6777b538SAndroid Build Coastguard Worker 374*6777b538SAndroid Build Coastguard Worker- (void)mergeFromCodedInputStream:(GPBCodedInputStream *)input { 375*6777b538SAndroid Build Coastguard Worker while (YES) { 376*6777b538SAndroid Build Coastguard Worker int32_t tag = GPBCodedInputStreamReadTag(&input->state_); 377*6777b538SAndroid Build Coastguard Worker if (tag == 0 || ![self mergeFieldFrom:tag input:input]) { 378*6777b538SAndroid Build Coastguard Worker break; 379*6777b538SAndroid Build Coastguard Worker } 380*6777b538SAndroid Build Coastguard Worker } 381*6777b538SAndroid Build Coastguard Worker} 382*6777b538SAndroid Build Coastguard Worker 383*6777b538SAndroid Build Coastguard Worker- (void)getTags:(int32_t *)tags { 384*6777b538SAndroid Build Coastguard Worker if (!fields_) return; 385*6777b538SAndroid Build Coastguard Worker size_t count = CFDictionaryGetCount(fields_); 386*6777b538SAndroid Build Coastguard Worker ssize_t keys[count]; 387*6777b538SAndroid Build Coastguard Worker CFDictionaryGetKeysAndValues(fields_, (const void **)keys, NULL); 388*6777b538SAndroid Build Coastguard Worker for (size_t i = 0; i < count; ++i) { 389*6777b538SAndroid Build Coastguard Worker tags[i] = (int32_t)keys[i]; 390*6777b538SAndroid Build Coastguard Worker } 391*6777b538SAndroid Build Coastguard Worker} 392*6777b538SAndroid Build Coastguard Worker 393*6777b538SAndroid Build Coastguard Worker#pragma clang diagnostic pop 394*6777b538SAndroid Build Coastguard Worker 395*6777b538SAndroid Build Coastguard Worker@end 396