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 424