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 |
39 #pragma mark Helpers | 72 #pragma mark Helpers |
40 | 73 |
41 static void checkNumber(int32_t number) { | 74 static void checkNumber(int32_t number) { |
42 if (number == 0) { | 75 if (number == 0) { |
43 [NSException raise:NSInvalidArgumentException | 76 [NSException raise:NSInvalidArgumentException |
44 format:@"Zero is not a valid field number."]; | 77 format:@"Zero is not a valid field number."]; |
45 } | 78 } |
46 } | 79 } |
47 | 80 |
48 @implementation GPBUnknownFieldSet { | 81 @implementation GPBUnknownFieldSet { |
49 @package | 82 @package |
50 CFMutableDictionaryRef fields_; | 83 CFMutableDictionaryRef fields_; |
51 } | 84 } |
52 | 85 |
53 static void CopyWorker(const void *key, const void *value, void *context) { | 86 static void CopyWorker(const void *key, const void *value, void *context) { |
54 #pragma unused(key) | 87 #pragma unused(key) |
55 GPBUnknownField *field = value; | 88 GPBUnknownField *field = value; |
56 GPBUnknownFieldSet *result = context; | 89 GPBUnknownFieldSet *result = context; |
57 | 90 |
58 GPBUnknownField *copied = [field copy]; | 91 GPBUnknownField *copied = [field copy]; |
59 [result addField:copied]; | 92 [result addField:copied]; |
60 [copied release]; | 93 [copied release]; |
61 } | 94 } |
62 | 95 |
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 | |
69 - (id)copyWithZone:(NSZone *)zone { | 96 - (id)copyWithZone:(NSZone *)zone { |
70 GPBUnknownFieldSet *result = [[GPBUnknownFieldSet allocWithZone:zone] init]; | 97 GPBUnknownFieldSet *result = [[GPBUnknownFieldSet allocWithZone:zone] init]; |
71 if (fields_) { | 98 if (fields_) { |
72 CFDictionaryApplyFunction(fields_, CopyWorker, result); | 99 CFDictionaryApplyFunction(fields_, CopyWorker, result); |
73 } | 100 } |
74 return result; | 101 return result; |
75 } | 102 } |
76 | 103 |
77 - (void)dealloc { | 104 - (void)dealloc { |
78 if (fields_) { | 105 if (fields_) { |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
114 GPBUnknownField *result = | 141 GPBUnknownField *result = |
115 fields_ ? CFDictionaryGetValue(fields_, (void *)key) : nil; | 142 fields_ ? CFDictionaryGetValue(fields_, (void *)key) : nil; |
116 return result; | 143 return result; |
117 } | 144 } |
118 | 145 |
119 - (NSUInteger)countOfFields { | 146 - (NSUInteger)countOfFields { |
120 return fields_ ? CFDictionaryGetCount(fields_) : 0; | 147 return fields_ ? CFDictionaryGetCount(fields_) : 0; |
121 } | 148 } |
122 | 149 |
123 - (NSArray *)sortedFields { | 150 - (NSArray *)sortedFields { |
124 if (!fields_) return [NSArray array]; | 151 if (!fields_) return nil; |
125 size_t count = CFDictionaryGetCount(fields_); | 152 size_t count = CFDictionaryGetCount(fields_); |
126 ssize_t keys[count]; | 153 ssize_t keys[count]; |
127 GPBUnknownField *values[count]; | 154 GPBUnknownField *values[count]; |
128 CFDictionaryGetKeysAndValues(fields_, (const void **)keys, | 155 CFDictionaryGetKeysAndValues(fields_, (const void **)keys, |
129 (const void **)values); | 156 (const void **)values); |
130 struct GPBFieldPair { | 157 struct GPBFieldPair { |
131 ssize_t key; | 158 ssize_t key; |
132 GPBUnknownField *value; | 159 GPBUnknownField *value; |
133 } pairs[count]; | 160 } pairs[count]; |
134 for (size_t i = 0; i < count; ++i) { | 161 for (size_t i = 0; i < count; ++i) { |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
251 } | 278 } |
252 | 279 |
253 + (BOOL)isFieldTag:(int32_t)tag { | 280 + (BOOL)isFieldTag:(int32_t)tag { |
254 return GPBWireFormatGetTagWireType(tag) != GPBWireFormatEndGroup; | 281 return GPBWireFormatGetTagWireType(tag) != GPBWireFormatEndGroup; |
255 } | 282 } |
256 | 283 |
257 - (void)addField:(GPBUnknownField *)field { | 284 - (void)addField:(GPBUnknownField *)field { |
258 int32_t number = [field number]; | 285 int32_t number = [field number]; |
259 checkNumber(number); | 286 checkNumber(number); |
260 if (!fields_) { | 287 if (!fields_) { |
261 // Use a custom dictionary here because the keys are numbers and conversion | 288 CFDictionaryKeyCallBacks keyCallBacks = { |
262 // back and forth from NSNumber isn't worth the cost. | 289 // See description above for reason for using custom dictionary. |
263 fields_ = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, NULL, | 290 0, GPBUnknownFieldSetKeyRetain, GPBUnknownFieldSetKeyRelease, |
| 291 GPBUnknownFieldSetCopyKeyDescription, GPBUnknownFieldSetKeyEqual, |
| 292 GPBUnknownFieldSetKeyHash, |
| 293 }; |
| 294 fields_ = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &keyCallBacks, |
264 &kCFTypeDictionaryValueCallBacks); | 295 &kCFTypeDictionaryValueCallBacks); |
265 } | 296 } |
266 ssize_t key = number; | 297 ssize_t key = number; |
267 CFDictionarySetValue(fields_, (const void *)key, field); | 298 CFDictionarySetValue(fields_, (const void *)key, field); |
268 } | 299 } |
269 | 300 |
270 - (GPBUnknownField *)mutableFieldForNumber:(int32_t)number create:(BOOL)create { | 301 - (GPBUnknownField *)mutableFieldForNumber:(int32_t)number create:(BOOL)create { |
271 ssize_t key = number; | 302 ssize_t key = number; |
272 GPBUnknownField *existing = | 303 GPBUnknownField *existing = |
273 fields_ ? CFDictionaryGetValue(fields_, (const void *)key) : nil; | 304 fields_ ? CFDictionaryGetValue(fields_, (const void *)key) : nil; |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
315 [input checkLastTagWas:0]; | 346 [input checkLastTagWas:0]; |
316 [input release]; | 347 [input release]; |
317 } | 348 } |
318 | 349 |
319 - (void)mergeVarintField:(int32_t)number value:(int32_t)value { | 350 - (void)mergeVarintField:(int32_t)number value:(int32_t)value { |
320 checkNumber(number); | 351 checkNumber(number); |
321 [[self mutableFieldForNumber:number create:YES] addVarint:value]; | 352 [[self mutableFieldForNumber:number create:YES] addVarint:value]; |
322 } | 353 } |
323 | 354 |
324 - (BOOL)mergeFieldFrom:(int32_t)tag input:(GPBCodedInputStream *)input { | 355 - (BOOL)mergeFieldFrom:(int32_t)tag input:(GPBCodedInputStream *)input { |
325 NSAssert(GPBWireFormatIsValidTag(tag), @"Got passed an invalid tag"); | |
326 int32_t number = GPBWireFormatGetTagFieldNumber(tag); | 356 int32_t number = GPBWireFormatGetTagFieldNumber(tag); |
327 GPBCodedInputStreamState *state = &input->state_; | 357 GPBCodedInputStreamState *state = &input->state_; |
328 switch (GPBWireFormatGetTagWireType(tag)) { | 358 switch (GPBWireFormatGetTagWireType(tag)) { |
329 case GPBWireFormatVarint: { | 359 case GPBWireFormatVarint: { |
330 GPBUnknownField *field = [self mutableFieldForNumber:number create:YES]; | 360 GPBUnknownField *field = [self mutableFieldForNumber:number create:YES]; |
331 [field addVarint:GPBCodedInputStreamReadInt64(state)]; | 361 [field addVarint:GPBCodedInputStreamReadInt64(state)]; |
332 return YES; | 362 return YES; |
333 } | 363 } |
334 case GPBWireFormatFixed64: { | 364 case GPBWireFormatFixed64: { |
335 GPBUnknownField *field = [self mutableFieldForNumber:number create:YES]; | 365 GPBUnknownField *field = [self mutableFieldForNumber:number create:YES]; |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
383 - (void)getTags:(int32_t *)tags { | 413 - (void)getTags:(int32_t *)tags { |
384 if (!fields_) return; | 414 if (!fields_) return; |
385 size_t count = CFDictionaryGetCount(fields_); | 415 size_t count = CFDictionaryGetCount(fields_); |
386 ssize_t keys[count]; | 416 ssize_t keys[count]; |
387 CFDictionaryGetKeysAndValues(fields_, (const void **)keys, NULL); | 417 CFDictionaryGetKeysAndValues(fields_, (const void **)keys, NULL); |
388 for (size_t i = 0; i < count; ++i) { | 418 for (size_t i = 0; i < count; ++i) { |
389 tags[i] = (int32_t)keys[i]; | 419 tags[i] = (int32_t)keys[i]; |
390 } | 420 } |
391 } | 421 } |
392 | 422 |
393 #pragma clang diagnostic pop | |
394 | |
395 @end | 423 @end |
OLD | NEW |