OLD | NEW |
1 // Protocol Buffers - Google's data interchange format | 1 // Protocol Buffers - Google's data interchange format |
2 // Copyright 2008 Google Inc. All rights reserved. | 2 // Copyright 2008 Google Inc. All rights reserved. |
3 // https://developers.google.com/protocol-buffers/ | 3 // https://developers.google.com/protocol-buffers/ |
4 // | 4 // |
5 // Redistribution and use in source and binary forms, with or without | 5 // Redistribution and use in source and binary forms, with or without |
6 // modification, are permitted provided that the following conditions are | 6 // modification, are permitted provided that the following conditions are |
7 // met: | 7 // met: |
8 // | 8 // |
9 // * Redistributions of source code must retain the above copyright | 9 // * Redistributions of source code must retain the above copyright |
10 // notice, this list of conditions and the following disclaimer. | 10 // notice, this list of conditions and the following disclaimer. |
(...skipping 18 matching lines...) Expand all Loading... |
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
30 | 30 |
31 #import "GPBUnknownFieldSet_PackagePrivate.h" | 31 #import "GPBUnknownFieldSet_PackagePrivate.h" |
32 | 32 |
33 #import "GPBCodedInputStream_PackagePrivate.h" | 33 #import "GPBCodedInputStream_PackagePrivate.h" |
34 #import "GPBCodedOutputStream.h" | 34 #import "GPBCodedOutputStream.h" |
35 #import "GPBUnknownField_PackagePrivate.h" | 35 #import "GPBUnknownField_PackagePrivate.h" |
36 #import "GPBUtilities.h" | 36 #import "GPBUtilities.h" |
37 #import "GPBWireFormat.h" | 37 #import "GPBWireFormat.h" |
38 | 38 |
39 #pragma mark CFDictionaryKeyCallBacks | |
40 | |
41 // We use a custom dictionary here because our keys are numbers and | |
42 // conversion back and forth from NSNumber was costing us performance. | |
43 // If/when we move to C++ this could be done using a std::map and some | |
44 // careful retain/release calls. | |
45 | |
46 static const void *GPBUnknownFieldSetKeyRetain(CFAllocatorRef allocator, | |
47 const void *value) { | |
48 #pragma unused(allocator) | |
49 return value; | |
50 } | |
51 | |
52 static void GPBUnknownFieldSetKeyRelease(CFAllocatorRef allocator, | |
53 const void *value) { | |
54 #pragma unused(allocator) | |
55 #pragma unused(value) | |
56 } | |
57 | |
58 static CFStringRef GPBUnknownFieldSetCopyKeyDescription(const void *value) { | |
59 return CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%d"), | |
60 (int)value); | |
61 } | |
62 | |
63 static Boolean GPBUnknownFieldSetKeyEqual(const void *value1, | |
64 const void *value2) { | |
65 return value1 == value2; | |
66 } | |
67 | |
68 static CFHashCode GPBUnknownFieldSetKeyHash(const void *value) { | |
69 return (CFHashCode)value; | |
70 } | |
71 | |
72 #pragma mark Helpers | 39 #pragma mark Helpers |
73 | 40 |
74 static void checkNumber(int32_t number) { | 41 static void checkNumber(int32_t number) { |
75 if (number == 0) { | 42 if (number == 0) { |
76 [NSException raise:NSInvalidArgumentException | 43 [NSException raise:NSInvalidArgumentException |
77 format:@"Zero is not a valid field number."]; | 44 format:@"Zero is not a valid field number."]; |
78 } | 45 } |
79 } | 46 } |
80 | 47 |
81 @implementation GPBUnknownFieldSet { | 48 @implementation GPBUnknownFieldSet { |
82 @package | 49 @package |
83 CFMutableDictionaryRef fields_; | 50 CFMutableDictionaryRef fields_; |
84 } | 51 } |
85 | 52 |
86 static void CopyWorker(const void *key, const void *value, void *context) { | 53 static void CopyWorker(const void *key, const void *value, void *context) { |
87 #pragma unused(key) | 54 #pragma unused(key) |
88 GPBUnknownField *field = value; | 55 GPBUnknownField *field = value; |
89 GPBUnknownFieldSet *result = context; | 56 GPBUnknownFieldSet *result = context; |
90 | 57 |
91 GPBUnknownField *copied = [field copy]; | 58 GPBUnknownField *copied = [field copy]; |
92 [result addField:copied]; | 59 [result addField:copied]; |
93 [copied release]; | 60 [copied release]; |
94 } | 61 } |
95 | 62 |
| 63 // Direct access is use for speed, to avoid even internally declaring things |
| 64 // read/write, etc. The warning is enabled in the project to ensure code calling |
| 65 // protos can turn on -Wdirect-ivar-access without issues. |
| 66 #pragma clang diagnostic push |
| 67 #pragma clang diagnostic ignored "-Wdirect-ivar-access" |
| 68 |
96 - (id)copyWithZone:(NSZone *)zone { | 69 - (id)copyWithZone:(NSZone *)zone { |
97 GPBUnknownFieldSet *result = [[GPBUnknownFieldSet allocWithZone:zone] init]; | 70 GPBUnknownFieldSet *result = [[GPBUnknownFieldSet allocWithZone:zone] init]; |
98 if (fields_) { | 71 if (fields_) { |
99 CFDictionaryApplyFunction(fields_, CopyWorker, result); | 72 CFDictionaryApplyFunction(fields_, CopyWorker, result); |
100 } | 73 } |
101 return result; | 74 return result; |
102 } | 75 } |
103 | 76 |
104 - (void)dealloc { | 77 - (void)dealloc { |
105 if (fields_) { | 78 if (fields_) { |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
141 GPBUnknownField *result = | 114 GPBUnknownField *result = |
142 fields_ ? CFDictionaryGetValue(fields_, (void *)key) : nil; | 115 fields_ ? CFDictionaryGetValue(fields_, (void *)key) : nil; |
143 return result; | 116 return result; |
144 } | 117 } |
145 | 118 |
146 - (NSUInteger)countOfFields { | 119 - (NSUInteger)countOfFields { |
147 return fields_ ? CFDictionaryGetCount(fields_) : 0; | 120 return fields_ ? CFDictionaryGetCount(fields_) : 0; |
148 } | 121 } |
149 | 122 |
150 - (NSArray *)sortedFields { | 123 - (NSArray *)sortedFields { |
151 if (!fields_) return nil; | 124 if (!fields_) return [NSArray array]; |
152 size_t count = CFDictionaryGetCount(fields_); | 125 size_t count = CFDictionaryGetCount(fields_); |
153 ssize_t keys[count]; | 126 ssize_t keys[count]; |
154 GPBUnknownField *values[count]; | 127 GPBUnknownField *values[count]; |
155 CFDictionaryGetKeysAndValues(fields_, (const void **)keys, | 128 CFDictionaryGetKeysAndValues(fields_, (const void **)keys, |
156 (const void **)values); | 129 (const void **)values); |
157 struct GPBFieldPair { | 130 struct GPBFieldPair { |
158 ssize_t key; | 131 ssize_t key; |
159 GPBUnknownField *value; | 132 GPBUnknownField *value; |
160 } pairs[count]; | 133 } pairs[count]; |
161 for (size_t i = 0; i < count; ++i) { | 134 for (size_t i = 0; i < count; ++i) { |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
278 } | 251 } |
279 | 252 |
280 + (BOOL)isFieldTag:(int32_t)tag { | 253 + (BOOL)isFieldTag:(int32_t)tag { |
281 return GPBWireFormatGetTagWireType(tag) != GPBWireFormatEndGroup; | 254 return GPBWireFormatGetTagWireType(tag) != GPBWireFormatEndGroup; |
282 } | 255 } |
283 | 256 |
284 - (void)addField:(GPBUnknownField *)field { | 257 - (void)addField:(GPBUnknownField *)field { |
285 int32_t number = [field number]; | 258 int32_t number = [field number]; |
286 checkNumber(number); | 259 checkNumber(number); |
287 if (!fields_) { | 260 if (!fields_) { |
288 CFDictionaryKeyCallBacks keyCallBacks = { | 261 // Use a custom dictionary here because the keys are numbers and conversion |
289 // See description above for reason for using custom dictionary. | 262 // back and forth from NSNumber isn't worth the cost. |
290 0, GPBUnknownFieldSetKeyRetain, GPBUnknownFieldSetKeyRelease, | 263 fields_ = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, NULL, |
291 GPBUnknownFieldSetCopyKeyDescription, GPBUnknownFieldSetKeyEqual, | |
292 GPBUnknownFieldSetKeyHash, | |
293 }; | |
294 fields_ = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &keyCallBacks, | |
295 &kCFTypeDictionaryValueCallBacks); | 264 &kCFTypeDictionaryValueCallBacks); |
296 } | 265 } |
297 ssize_t key = number; | 266 ssize_t key = number; |
298 CFDictionarySetValue(fields_, (const void *)key, field); | 267 CFDictionarySetValue(fields_, (const void *)key, field); |
299 } | 268 } |
300 | 269 |
301 - (GPBUnknownField *)mutableFieldForNumber:(int32_t)number create:(BOOL)create { | 270 - (GPBUnknownField *)mutableFieldForNumber:(int32_t)number create:(BOOL)create { |
302 ssize_t key = number; | 271 ssize_t key = number; |
303 GPBUnknownField *existing = | 272 GPBUnknownField *existing = |
304 fields_ ? CFDictionaryGetValue(fields_, (const void *)key) : nil; | 273 fields_ ? CFDictionaryGetValue(fields_, (const void *)key) : nil; |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
346 [input checkLastTagWas:0]; | 315 [input checkLastTagWas:0]; |
347 [input release]; | 316 [input release]; |
348 } | 317 } |
349 | 318 |
350 - (void)mergeVarintField:(int32_t)number value:(int32_t)value { | 319 - (void)mergeVarintField:(int32_t)number value:(int32_t)value { |
351 checkNumber(number); | 320 checkNumber(number); |
352 [[self mutableFieldForNumber:number create:YES] addVarint:value]; | 321 [[self mutableFieldForNumber:number create:YES] addVarint:value]; |
353 } | 322 } |
354 | 323 |
355 - (BOOL)mergeFieldFrom:(int32_t)tag input:(GPBCodedInputStream *)input { | 324 - (BOOL)mergeFieldFrom:(int32_t)tag input:(GPBCodedInputStream *)input { |
| 325 NSAssert(GPBWireFormatIsValidTag(tag), @"Got passed an invalid tag"); |
356 int32_t number = GPBWireFormatGetTagFieldNumber(tag); | 326 int32_t number = GPBWireFormatGetTagFieldNumber(tag); |
357 GPBCodedInputStreamState *state = &input->state_; | 327 GPBCodedInputStreamState *state = &input->state_; |
358 switch (GPBWireFormatGetTagWireType(tag)) { | 328 switch (GPBWireFormatGetTagWireType(tag)) { |
359 case GPBWireFormatVarint: { | 329 case GPBWireFormatVarint: { |
360 GPBUnknownField *field = [self mutableFieldForNumber:number create:YES]; | 330 GPBUnknownField *field = [self mutableFieldForNumber:number create:YES]; |
361 [field addVarint:GPBCodedInputStreamReadInt64(state)]; | 331 [field addVarint:GPBCodedInputStreamReadInt64(state)]; |
362 return YES; | 332 return YES; |
363 } | 333 } |
364 case GPBWireFormatFixed64: { | 334 case GPBWireFormatFixed64: { |
365 GPBUnknownField *field = [self mutableFieldForNumber:number create:YES]; | 335 GPBUnknownField *field = [self mutableFieldForNumber:number create:YES]; |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
413 - (void)getTags:(int32_t *)tags { | 383 - (void)getTags:(int32_t *)tags { |
414 if (!fields_) return; | 384 if (!fields_) return; |
415 size_t count = CFDictionaryGetCount(fields_); | 385 size_t count = CFDictionaryGetCount(fields_); |
416 ssize_t keys[count]; | 386 ssize_t keys[count]; |
417 CFDictionaryGetKeysAndValues(fields_, (const void **)keys, NULL); | 387 CFDictionaryGetKeysAndValues(fields_, (const void **)keys, NULL); |
418 for (size_t i = 0; i < count; ++i) { | 388 for (size_t i = 0; i < count; ++i) { |
419 tags[i] = (int32_t)keys[i]; | 389 tags[i] = (int32_t)keys[i]; |
420 } | 390 } |
421 } | 391 } |
422 | 392 |
| 393 #pragma clang diagnostic pop |
| 394 |
423 @end | 395 @end |
OLD | NEW |