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