| OLD | NEW |
| (Empty) |
| 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 "GPBUnknownFieldSet_PackagePrivate.h" | |
| 32 | |
| 33 #import "GPBCodedInputStream_PackagePrivate.h" | |
| 34 #import "GPBCodedOutputStream.h" | |
| 35 #import "GPBUnknownField_PackagePrivate.h" | |
| 36 #import "GPBUtilities.h" | |
| 37 #import "GPBWireFormat.h" | |
| 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 | |
| 73 | |
| 74 static void checkNumber(int32_t number) { | |
| 75 if (number == 0) { | |
| 76 [NSException raise:NSInvalidArgumentException | |
| 77 format:@"Zero is not a valid field number."]; | |
| 78 } | |
| 79 } | |
| 80 | |
| 81 @implementation GPBUnknownFieldSet { | |
| 82 @package | |
| 83 CFMutableDictionaryRef fields_; | |
| 84 } | |
| 85 | |
| 86 static void CopyWorker(const void *key, const void *value, void *context) { | |
| 87 #pragma unused(key) | |
| 88 GPBUnknownField *field = value; | |
| 89 GPBUnknownFieldSet *result = context; | |
| 90 | |
| 91 GPBUnknownField *copied = [field copy]; | |
| 92 [result addField:copied]; | |
| 93 [copied release]; | |
| 94 } | |
| 95 | |
| 96 - (id)copyWithZone:(NSZone *)zone { | |
| 97 GPBUnknownFieldSet *result = [[GPBUnknownFieldSet allocWithZone:zone] init]; | |
| 98 if (fields_) { | |
| 99 CFDictionaryApplyFunction(fields_, CopyWorker, result); | |
| 100 } | |
| 101 return result; | |
| 102 } | |
| 103 | |
| 104 - (void)dealloc { | |
| 105 if (fields_) { | |
| 106 CFRelease(fields_); | |
| 107 } | |
| 108 [super dealloc]; | |
| 109 } | |
| 110 | |
| 111 - (BOOL)isEqual:(id)object { | |
| 112 BOOL equal = NO; | |
| 113 if ([object isKindOfClass:[GPBUnknownFieldSet class]]) { | |
| 114 GPBUnknownFieldSet *set = (GPBUnknownFieldSet *)object; | |
| 115 if ((fields_ == NULL) && (set->fields_ == NULL)) { | |
| 116 equal = YES; | |
| 117 } else if ((fields_ != NULL) && (set->fields_ != NULL)) { | |
| 118 equal = CFEqual(fields_, set->fields_); | |
| 119 } | |
| 120 } | |
| 121 return equal; | |
| 122 } | |
| 123 | |
| 124 - (NSUInteger)hash { | |
| 125 // Return the hash of the fields dictionary (or just some value). | |
| 126 if (fields_) { | |
| 127 return CFHash(fields_); | |
| 128 } | |
| 129 return (NSUInteger)[GPBUnknownFieldSet class]; | |
| 130 } | |
| 131 | |
| 132 #pragma mark - Public Methods | |
| 133 | |
| 134 - (BOOL)hasField:(int32_t)number { | |
| 135 ssize_t key = number; | |
| 136 return fields_ ? (CFDictionaryGetValue(fields_, (void *)key) != nil) : NO; | |
| 137 } | |
| 138 | |
| 139 - (GPBUnknownField *)getField:(int32_t)number { | |
| 140 ssize_t key = number; | |
| 141 GPBUnknownField *result = | |
| 142 fields_ ? CFDictionaryGetValue(fields_, (void *)key) : nil; | |
| 143 return result; | |
| 144 } | |
| 145 | |
| 146 - (NSUInteger)countOfFields { | |
| 147 return fields_ ? CFDictionaryGetCount(fields_) : 0; | |
| 148 } | |
| 149 | |
| 150 - (NSArray *)sortedFields { | |
| 151 if (!fields_) return nil; | |
| 152 size_t count = CFDictionaryGetCount(fields_); | |
| 153 ssize_t keys[count]; | |
| 154 GPBUnknownField *values[count]; | |
| 155 CFDictionaryGetKeysAndValues(fields_, (const void **)keys, | |
| 156 (const void **)values); | |
| 157 struct GPBFieldPair { | |
| 158 ssize_t key; | |
| 159 GPBUnknownField *value; | |
| 160 } pairs[count]; | |
| 161 for (size_t i = 0; i < count; ++i) { | |
| 162 pairs[i].key = keys[i]; | |
| 163 pairs[i].value = values[i]; | |
| 164 }; | |
| 165 qsort_b(pairs, count, sizeof(struct GPBFieldPair), | |
| 166 ^(const void *first, const void *second) { | |
| 167 const struct GPBFieldPair *a = first; | |
| 168 const struct GPBFieldPair *b = second; | |
| 169 return (a->key > b->key) ? 1 : ((a->key == b->key) ? 0 : -1); | |
| 170 }); | |
| 171 for (size_t i = 0; i < count; ++i) { | |
| 172 values[i] = pairs[i].value; | |
| 173 }; | |
| 174 return [NSArray arrayWithObjects:values count:count]; | |
| 175 } | |
| 176 | |
| 177 #pragma mark - Internal Methods | |
| 178 | |
| 179 - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)output { | |
| 180 if (!fields_) return; | |
| 181 size_t count = CFDictionaryGetCount(fields_); | |
| 182 ssize_t keys[count]; | |
| 183 GPBUnknownField *values[count]; | |
| 184 CFDictionaryGetKeysAndValues(fields_, (const void **)keys, | |
| 185 (const void **)values); | |
| 186 if (count > 1) { | |
| 187 struct GPBFieldPair { | |
| 188 ssize_t key; | |
| 189 GPBUnknownField *value; | |
| 190 } pairs[count]; | |
| 191 | |
| 192 for (size_t i = 0; i < count; ++i) { | |
| 193 pairs[i].key = keys[i]; | |
| 194 pairs[i].value = values[i]; | |
| 195 }; | |
| 196 qsort_b(pairs, count, sizeof(struct GPBFieldPair), | |
| 197 ^(const void *first, const void *second) { | |
| 198 const struct GPBFieldPair *a = first; | |
| 199 const struct GPBFieldPair *b = second; | |
| 200 return (a->key > b->key) ? 1 : ((a->key == b->key) ? 0 : -1); | |
| 201 }); | |
| 202 for (size_t i = 0; i < count; ++i) { | |
| 203 GPBUnknownField *value = pairs[i].value; | |
| 204 [value writeToOutput:output]; | |
| 205 } | |
| 206 } else { | |
| 207 [values[0] writeToOutput:output]; | |
| 208 } | |
| 209 } | |
| 210 | |
| 211 - (NSString *)description { | |
| 212 NSMutableString *description = [NSMutableString | |
| 213 stringWithFormat:@"<%@ %p>: TextFormat: {\n", [self class], self]; | |
| 214 NSString *textFormat = GPBTextFormatForUnknownFieldSet(self, @" "); | |
| 215 [description appendString:textFormat]; | |
| 216 [description appendString:@"}"]; | |
| 217 return description; | |
| 218 } | |
| 219 | |
| 220 static void GPBUnknownFieldSetSerializedSize(const void *key, const void *value, | |
| 221 void *context) { | |
| 222 #pragma unused(key) | |
| 223 GPBUnknownField *field = value; | |
| 224 size_t *result = context; | |
| 225 *result += [field serializedSize]; | |
| 226 } | |
| 227 | |
| 228 - (size_t)serializedSize { | |
| 229 size_t result = 0; | |
| 230 if (fields_) { | |
| 231 CFDictionaryApplyFunction(fields_, GPBUnknownFieldSetSerializedSize, | |
| 232 &result); | |
| 233 } | |
| 234 return result; | |
| 235 } | |
| 236 | |
| 237 static void GPBUnknownFieldSetWriteAsMessageSetTo(const void *key, | |
| 238 const void *value, | |
| 239 void *context) { | |
| 240 #pragma unused(key) | |
| 241 GPBUnknownField *field = value; | |
| 242 GPBCodedOutputStream *output = context; | |
| 243 [field writeAsMessageSetExtensionToOutput:output]; | |
| 244 } | |
| 245 | |
| 246 - (void)writeAsMessageSetTo:(GPBCodedOutputStream *)output { | |
| 247 if (fields_) { | |
| 248 CFDictionaryApplyFunction(fields_, GPBUnknownFieldSetWriteAsMessageSetTo, | |
| 249 output); | |
| 250 } | |
| 251 } | |
| 252 | |
| 253 static void GPBUnknownFieldSetSerializedSizeAsMessageSet(const void *key, | |
| 254 const void *value, | |
| 255 void *context) { | |
| 256 #pragma unused(key) | |
| 257 GPBUnknownField *field = value; | |
| 258 size_t *result = context; | |
| 259 *result += [field serializedSizeAsMessageSetExtension]; | |
| 260 } | |
| 261 | |
| 262 - (size_t)serializedSizeAsMessageSet { | |
| 263 size_t result = 0; | |
| 264 if (fields_) { | |
| 265 CFDictionaryApplyFunction( | |
| 266 fields_, GPBUnknownFieldSetSerializedSizeAsMessageSet, &result); | |
| 267 } | |
| 268 return result; | |
| 269 } | |
| 270 | |
| 271 - (NSData *)data { | |
| 272 NSMutableData *data = [NSMutableData dataWithLength:self.serializedSize]; | |
| 273 GPBCodedOutputStream *output = | |
| 274 [[GPBCodedOutputStream alloc] initWithData:data]; | |
| 275 [self writeToCodedOutputStream:output]; | |
| 276 [output release]; | |
| 277 return data; | |
| 278 } | |
| 279 | |
| 280 + (BOOL)isFieldTag:(int32_t)tag { | |
| 281 return GPBWireFormatGetTagWireType(tag) != GPBWireFormatEndGroup; | |
| 282 } | |
| 283 | |
| 284 - (void)addField:(GPBUnknownField *)field { | |
| 285 int32_t number = [field number]; | |
| 286 checkNumber(number); | |
| 287 if (!fields_) { | |
| 288 CFDictionaryKeyCallBacks keyCallBacks = { | |
| 289 // See description above for reason for using custom dictionary. | |
| 290 0, GPBUnknownFieldSetKeyRetain, GPBUnknownFieldSetKeyRelease, | |
| 291 GPBUnknownFieldSetCopyKeyDescription, GPBUnknownFieldSetKeyEqual, | |
| 292 GPBUnknownFieldSetKeyHash, | |
| 293 }; | |
| 294 fields_ = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &keyCallBacks, | |
| 295 &kCFTypeDictionaryValueCallBacks); | |
| 296 } | |
| 297 ssize_t key = number; | |
| 298 CFDictionarySetValue(fields_, (const void *)key, field); | |
| 299 } | |
| 300 | |
| 301 - (GPBUnknownField *)mutableFieldForNumber:(int32_t)number create:(BOOL)create { | |
| 302 ssize_t key = number; | |
| 303 GPBUnknownField *existing = | |
| 304 fields_ ? CFDictionaryGetValue(fields_, (const void *)key) : nil; | |
| 305 if (!existing && create) { | |
| 306 existing = [[GPBUnknownField alloc] initWithNumber:number]; | |
| 307 // This retains existing. | |
| 308 [self addField:existing]; | |
| 309 [existing release]; | |
| 310 } | |
| 311 return existing; | |
| 312 } | |
| 313 | |
| 314 static void GPBUnknownFieldSetMergeUnknownFields(const void *key, | |
| 315 const void *value, | |
| 316 void *context) { | |
| 317 #pragma unused(key) | |
| 318 GPBUnknownField *field = value; | |
| 319 GPBUnknownFieldSet *self = context; | |
| 320 | |
| 321 int32_t number = [field number]; | |
| 322 checkNumber(number); | |
| 323 GPBUnknownField *oldField = [self mutableFieldForNumber:number create:NO]; | |
| 324 if (oldField) { | |
| 325 [oldField mergeFromField:field]; | |
| 326 } else { | |
| 327 // Merge only comes from GPBMessage's mergeFrom:, so it means we are on | |
| 328 // mutable message and are an mutable instance, so make sure we need | |
| 329 // mutable fields. | |
| 330 GPBUnknownField *fieldCopy = [field copy]; | |
| 331 [self addField:fieldCopy]; | |
| 332 [fieldCopy release]; | |
| 333 } | |
| 334 } | |
| 335 | |
| 336 - (void)mergeUnknownFields:(GPBUnknownFieldSet *)other { | |
| 337 if (other && other->fields_) { | |
| 338 CFDictionaryApplyFunction(other->fields_, | |
| 339 GPBUnknownFieldSetMergeUnknownFields, self); | |
| 340 } | |
| 341 } | |
| 342 | |
| 343 - (void)mergeFromData:(NSData *)data { | |
| 344 GPBCodedInputStream *input = [[GPBCodedInputStream alloc] initWithData:data]; | |
| 345 [self mergeFromCodedInputStream:input]; | |
| 346 [input checkLastTagWas:0]; | |
| 347 [input release]; | |
| 348 } | |
| 349 | |
| 350 - (void)mergeVarintField:(int32_t)number value:(int32_t)value { | |
| 351 checkNumber(number); | |
| 352 [[self mutableFieldForNumber:number create:YES] addVarint:value]; | |
| 353 } | |
| 354 | |
| 355 - (BOOL)mergeFieldFrom:(int32_t)tag input:(GPBCodedInputStream *)input { | |
| 356 int32_t number = GPBWireFormatGetTagFieldNumber(tag); | |
| 357 GPBCodedInputStreamState *state = &input->state_; | |
| 358 switch (GPBWireFormatGetTagWireType(tag)) { | |
| 359 case GPBWireFormatVarint: { | |
| 360 GPBUnknownField *field = [self mutableFieldForNumber:number create:YES]; | |
| 361 [field addVarint:GPBCodedInputStreamReadInt64(state)]; | |
| 362 return YES; | |
| 363 } | |
| 364 case GPBWireFormatFixed64: { | |
| 365 GPBUnknownField *field = [self mutableFieldForNumber:number create:YES]; | |
| 366 [field addFixed64:GPBCodedInputStreamReadFixed64(state)]; | |
| 367 return YES; | |
| 368 } | |
| 369 case GPBWireFormatLengthDelimited: { | |
| 370 NSData *data = GPBCodedInputStreamReadRetainedBytes(state); | |
| 371 GPBUnknownField *field = [self mutableFieldForNumber:number create:YES]; | |
| 372 [field addLengthDelimited:data]; | |
| 373 [data release]; | |
| 374 return YES; | |
| 375 } | |
| 376 case GPBWireFormatStartGroup: { | |
| 377 GPBUnknownFieldSet *unknownFieldSet = [[GPBUnknownFieldSet alloc] init]; | |
| 378 [input readUnknownGroup:number message:unknownFieldSet]; | |
| 379 GPBUnknownField *field = [self mutableFieldForNumber:number create:YES]; | |
| 380 [field addGroup:unknownFieldSet]; | |
| 381 [unknownFieldSet release]; | |
| 382 return YES; | |
| 383 } | |
| 384 case GPBWireFormatEndGroup: | |
| 385 return NO; | |
| 386 case GPBWireFormatFixed32: { | |
| 387 GPBUnknownField *field = [self mutableFieldForNumber:number create:YES]; | |
| 388 [field addFixed32:GPBCodedInputStreamReadFixed32(state)]; | |
| 389 return YES; | |
| 390 } | |
| 391 } | |
| 392 } | |
| 393 | |
| 394 - (void)mergeMessageSetMessage:(int32_t)number data:(NSData *)messageData { | |
| 395 [[self mutableFieldForNumber:number create:YES] | |
| 396 addLengthDelimited:messageData]; | |
| 397 } | |
| 398 | |
| 399 - (void)addUnknownMapEntry:(int32_t)fieldNum value:(NSData *)data { | |
| 400 GPBUnknownField *field = [self mutableFieldForNumber:fieldNum create:YES]; | |
| 401 [field addLengthDelimited:data]; | |
| 402 } | |
| 403 | |
| 404 - (void)mergeFromCodedInputStream:(GPBCodedInputStream *)input { | |
| 405 while (YES) { | |
| 406 int32_t tag = GPBCodedInputStreamReadTag(&input->state_); | |
| 407 if (tag == 0 || ![self mergeFieldFrom:tag input:input]) { | |
| 408 break; | |
| 409 } | |
| 410 } | |
| 411 } | |
| 412 | |
| 413 - (void)getTags:(int32_t *)tags { | |
| 414 if (!fields_) return; | |
| 415 size_t count = CFDictionaryGetCount(fields_); | |
| 416 ssize_t keys[count]; | |
| 417 CFDictionaryGetKeysAndValues(fields_, (const void **)keys, NULL); | |
| 418 for (size_t i = 0; i < count; ++i) { | |
| 419 tags[i] = (int32_t)keys[i]; | |
| 420 } | |
| 421 } | |
| 422 | |
| 423 @end | |
| OLD | NEW |