1// Protocol Buffers - Google's data interchange format
2// Copyright 2008 Google Inc.  All rights reserved.
3// https://developers.google.com/protocol-buffers/
4//
5// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are
7// met:
8//
9//     * Redistributions of source code must retain the above copyright
10// notice, this list of conditions and the following disclaimer.
11//     * Redistributions in binary form must reproduce the above
12// copyright notice, this list of conditions and the following disclaimer
13// in the documentation and/or other materials provided with the
14// distribution.
15//     * Neither the name of Google Inc. nor the names of its
16// contributors may be used to endorse or promote products derived from
17// this software without specific prior written permission.
18//
19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31#import "GPBUnknownField_PackagePrivate.h"
32
33#import "GPBArray.h"
34#import "GPBCodedOutputStream_PackagePrivate.h"
35
36@implementation GPBUnknownField {
37 @protected
38  int32_t number_;
39  GPBUInt64Array *mutableVarintList_;
40  GPBUInt32Array *mutableFixed32List_;
41  GPBUInt64Array *mutableFixed64List_;
42  NSMutableArray<NSData*> *mutableLengthDelimitedList_;
43  NSMutableArray<GPBUnknownFieldSet*> *mutableGroupList_;
44}
45
46@synthesize number = number_;
47@synthesize varintList = mutableVarintList_;
48@synthesize fixed32List = mutableFixed32List_;
49@synthesize fixed64List = mutableFixed64List_;
50@synthesize lengthDelimitedList = mutableLengthDelimitedList_;
51@synthesize groupList = mutableGroupList_;
52
53- (instancetype)initWithNumber:(int32_t)number {
54  if ((self = [super init])) {
55    number_ = number;
56  }
57  return self;
58}
59
60- (void)dealloc {
61  [mutableVarintList_ release];
62  [mutableFixed32List_ release];
63  [mutableFixed64List_ release];
64  [mutableLengthDelimitedList_ release];
65  [mutableGroupList_ release];
66
67  [super dealloc];
68}
69
70// Direct access is use for speed, to avoid even internally declaring things
71// read/write, etc. The warning is enabled in the project to ensure code calling
72// protos can turn on -Wdirect-ivar-access without issues.
73#pragma clang diagnostic push
74#pragma clang diagnostic ignored "-Wdirect-ivar-access"
75
76- (id)copyWithZone:(NSZone *)zone {
77  GPBUnknownField *result =
78      [[GPBUnknownField allocWithZone:zone] initWithNumber:number_];
79  result->mutableFixed32List_ = [mutableFixed32List_ copyWithZone:zone];
80  result->mutableFixed64List_ = [mutableFixed64List_ copyWithZone:zone];
81  result->mutableLengthDelimitedList_ =
82      [mutableLengthDelimitedList_ copyWithZone:zone];
83  result->mutableVarintList_ = [mutableVarintList_ copyWithZone:zone];
84  if (mutableGroupList_.count) {
85    result->mutableGroupList_ = [[NSMutableArray allocWithZone:zone]
86        initWithCapacity:mutableGroupList_.count];
87    for (GPBUnknownFieldSet *group in mutableGroupList_) {
88      GPBUnknownFieldSet *copied = [group copyWithZone:zone];
89      [result->mutableGroupList_ addObject:copied];
90      [copied release];
91    }
92  }
93  return result;
94}
95
96- (BOOL)isEqual:(id)object {
97  if (self == object) return YES;
98  if (![object isKindOfClass:[GPBUnknownField class]]) return NO;
99  GPBUnknownField *field = (GPBUnknownField *)object;
100  BOOL equalVarint =
101      (mutableVarintList_.count == 0 && field->mutableVarintList_.count == 0) ||
102      [mutableVarintList_ isEqual:field->mutableVarintList_];
103  if (!equalVarint) return NO;
104  BOOL equalFixed32 = (mutableFixed32List_.count == 0 &&
105                       field->mutableFixed32List_.count == 0) ||
106                      [mutableFixed32List_ isEqual:field->mutableFixed32List_];
107  if (!equalFixed32) return NO;
108  BOOL equalFixed64 = (mutableFixed64List_.count == 0 &&
109                       field->mutableFixed64List_.count == 0) ||
110                      [mutableFixed64List_ isEqual:field->mutableFixed64List_];
111  if (!equalFixed64) return NO;
112  BOOL equalLDList =
113      (mutableLengthDelimitedList_.count == 0 &&
114       field->mutableLengthDelimitedList_.count == 0) ||
115      [mutableLengthDelimitedList_ isEqual:field->mutableLengthDelimitedList_];
116  if (!equalLDList) return NO;
117  BOOL equalGroupList =
118      (mutableGroupList_.count == 0 && field->mutableGroupList_.count == 0) ||
119      [mutableGroupList_ isEqual:field->mutableGroupList_];
120  if (!equalGroupList) return NO;
121  return YES;
122}
123
124- (NSUInteger)hash {
125  // Just mix the hashes of the possible sub arrays.
126  const int prime = 31;
127  NSUInteger result = prime + [mutableVarintList_ hash];
128  result = prime * result + [mutableFixed32List_ hash];
129  result = prime * result + [mutableFixed64List_ hash];
130  result = prime * result + [mutableLengthDelimitedList_ hash];
131  result = prime * result + [mutableGroupList_ hash];
132  return result;
133}
134
135- (void)writeToOutput:(GPBCodedOutputStream *)output {
136  NSUInteger count = mutableVarintList_.count;
137  if (count > 0) {
138    [output writeUInt64Array:number_ values:mutableVarintList_ tag:0];
139  }
140  count = mutableFixed32List_.count;
141  if (count > 0) {
142    [output writeFixed32Array:number_ values:mutableFixed32List_ tag:0];
143  }
144  count = mutableFixed64List_.count;
145  if (count > 0) {
146    [output writeFixed64Array:number_ values:mutableFixed64List_ tag:0];
147  }
148  count = mutableLengthDelimitedList_.count;
149  if (count > 0) {
150    [output writeBytesArray:number_ values:mutableLengthDelimitedList_];
151  }
152  count = mutableGroupList_.count;
153  if (count > 0) {
154    [output writeUnknownGroupArray:number_ values:mutableGroupList_];
155  }
156}
157
158- (size_t)serializedSize {
159  __block size_t result = 0;
160  int32_t number = number_;
161  [mutableVarintList_
162      enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
163#pragma unused(idx, stop)
164        result += GPBComputeUInt64Size(number, value);
165      }];
166
167  [mutableFixed32List_
168      enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
169#pragma unused(idx, stop)
170        result += GPBComputeFixed32Size(number, value);
171      }];
172
173  [mutableFixed64List_
174      enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
175#pragma unused(idx, stop)
176        result += GPBComputeFixed64Size(number, value);
177      }];
178
179  for (NSData *data in mutableLengthDelimitedList_) {
180    result += GPBComputeBytesSize(number, data);
181  }
182
183  for (GPBUnknownFieldSet *set in mutableGroupList_) {
184    result += GPBComputeUnknownGroupSize(number, set);
185  }
186
187  return result;
188}
189
190- (void)writeAsMessageSetExtensionToOutput:(GPBCodedOutputStream *)output {
191  for (NSData *data in mutableLengthDelimitedList_) {
192    [output writeRawMessageSetExtension:number_ value:data];
193  }
194}
195
196- (size_t)serializedSizeAsMessageSetExtension {
197  size_t result = 0;
198  for (NSData *data in mutableLengthDelimitedList_) {
199    result += GPBComputeRawMessageSetExtensionSize(number_, data);
200  }
201  return result;
202}
203
204- (NSString *)description {
205  NSMutableString *description = [NSMutableString
206      stringWithFormat:@"<%@ %p>: Field: %d {\n", [self class], self, number_];
207  [mutableVarintList_
208      enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
209#pragma unused(idx, stop)
210        [description appendFormat:@"\t%llu\n", value];
211      }];
212
213  [mutableFixed32List_
214      enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
215#pragma unused(idx, stop)
216        [description appendFormat:@"\t%u\n", value];
217      }];
218
219  [mutableFixed64List_
220      enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
221#pragma unused(idx, stop)
222        [description appendFormat:@"\t%llu\n", value];
223      }];
224
225  for (NSData *data in mutableLengthDelimitedList_) {
226    [description appendFormat:@"\t%@\n", data];
227  }
228
229  for (GPBUnknownFieldSet *set in mutableGroupList_) {
230    [description appendFormat:@"\t%@\n", set];
231  }
232  [description appendString:@"}"];
233  return description;
234}
235
236- (void)mergeFromField:(GPBUnknownField *)other {
237  GPBUInt64Array *otherVarintList = other.varintList;
238  if (otherVarintList.count > 0) {
239    if (mutableVarintList_ == nil) {
240      mutableVarintList_ = [otherVarintList copy];
241    } else {
242      [mutableVarintList_ addValuesFromArray:otherVarintList];
243    }
244  }
245
246  GPBUInt32Array *otherFixed32List = other.fixed32List;
247  if (otherFixed32List.count > 0) {
248    if (mutableFixed32List_ == nil) {
249      mutableFixed32List_ = [otherFixed32List copy];
250    } else {
251      [mutableFixed32List_ addValuesFromArray:otherFixed32List];
252    }
253  }
254
255  GPBUInt64Array *otherFixed64List = other.fixed64List;
256  if (otherFixed64List.count > 0) {
257    if (mutableFixed64List_ == nil) {
258      mutableFixed64List_ = [otherFixed64List copy];
259    } else {
260      [mutableFixed64List_ addValuesFromArray:otherFixed64List];
261    }
262  }
263
264  NSArray *otherLengthDelimitedList = other.lengthDelimitedList;
265  if (otherLengthDelimitedList.count > 0) {
266    if (mutableLengthDelimitedList_ == nil) {
267      mutableLengthDelimitedList_ = [otherLengthDelimitedList mutableCopy];
268    } else {
269      [mutableLengthDelimitedList_
270          addObjectsFromArray:otherLengthDelimitedList];
271    }
272  }
273
274  NSArray *otherGroupList = other.groupList;
275  if (otherGroupList.count > 0) {
276    if (mutableGroupList_ == nil) {
277      mutableGroupList_ =
278          [[NSMutableArray alloc] initWithCapacity:otherGroupList.count];
279    }
280    // Make our own mutable copies.
281    for (GPBUnknownFieldSet *group in otherGroupList) {
282      GPBUnknownFieldSet *copied = [group copy];
283      [mutableGroupList_ addObject:copied];
284      [copied release];
285    }
286  }
287}
288
289- (void)addVarint:(uint64_t)value {
290  if (mutableVarintList_ == nil) {
291    mutableVarintList_ = [[GPBUInt64Array alloc] initWithValues:&value count:1];
292  } else {
293    [mutableVarintList_ addValue:value];
294  }
295}
296
297- (void)addFixed32:(uint32_t)value {
298  if (mutableFixed32List_ == nil) {
299    mutableFixed32List_ =
300        [[GPBUInt32Array alloc] initWithValues:&value count:1];
301  } else {
302    [mutableFixed32List_ addValue:value];
303  }
304}
305
306- (void)addFixed64:(uint64_t)value {
307  if (mutableFixed64List_ == nil) {
308    mutableFixed64List_ =
309        [[GPBUInt64Array alloc] initWithValues:&value count:1];
310  } else {
311    [mutableFixed64List_ addValue:value];
312  }
313}
314
315- (void)addLengthDelimited:(NSData *)value {
316  if (mutableLengthDelimitedList_ == nil) {
317    mutableLengthDelimitedList_ =
318        [[NSMutableArray alloc] initWithObjects:&value count:1];
319  } else {
320    [mutableLengthDelimitedList_ addObject:value];
321  }
322}
323
324- (void)addGroup:(GPBUnknownFieldSet *)value {
325  if (mutableGroupList_ == nil) {
326    mutableGroupList_ = [[NSMutableArray alloc] initWithObjects:&value count:1];
327  } else {
328    [mutableGroupList_ addObject:value];
329  }
330}
331
332#pragma clang diagnostic pop
333
334@end
335