xref: /aosp_15_r20/external/cronet/third_party/protobuf/objectivec/GPBUnknownFieldSet.m (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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