| 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 |