Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3)

Side by Side Diff: third_party/protobuf/objectivec/GPBDescriptor.m

Issue 1842653006: Update //third_party/protobuf to version 3. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: merge Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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 "GPBDescriptor_PackagePrivate.h"
32
33 #import <objc/runtime.h>
34
35 #import "GPBUtilities_PackagePrivate.h"
36 #import "GPBWireFormat.h"
37 #import "GPBMessage_PackagePrivate.h"
38 #import "google/protobuf/Descriptor.pbobjc.h"
39
40 // The address of this variable is used as a key for obj_getAssociatedObject.
41 static const char kTextFormatExtraValueKey = 0;
42
43 // Utility function to generate selectors on the fly.
44 static SEL SelFromStrings(const char *prefix, const char *middle,
45 const char *suffix, BOOL takesArg) {
46 if (prefix == NULL && suffix == NULL && !takesArg) {
47 return sel_getUid(middle);
48 }
49 const size_t prefixLen = prefix != NULL ? strlen(prefix) : 0;
50 const size_t middleLen = strlen(middle);
51 const size_t suffixLen = suffix != NULL ? strlen(suffix) : 0;
52 size_t totalLen =
53 prefixLen + middleLen + suffixLen + 1; // include space for null on end.
54 if (takesArg) {
55 totalLen += 1;
56 }
57 char buffer[totalLen];
58 if (prefix != NULL) {
59 memcpy(buffer, prefix, prefixLen);
60 memcpy(buffer + prefixLen, middle, middleLen);
61 buffer[prefixLen] = (char)toupper(buffer[prefixLen]);
62 } else {
63 memcpy(buffer, middle, middleLen);
64 }
65 if (suffix != NULL) {
66 memcpy(buffer + prefixLen + middleLen, suffix, suffixLen);
67 }
68 if (takesArg) {
69 buffer[totalLen - 2] = ':';
70 }
71 // Always null terminate it.
72 buffer[totalLen - 1] = 0;
73
74 SEL result = sel_getUid(buffer);
75 return result;
76 }
77
78 static NSArray *NewFieldsArrayForHasIndex(int hasIndex,
79 NSArray *allMessageFields)
80 __attribute__((ns_returns_retained));
81
82 static NSArray *NewFieldsArrayForHasIndex(int hasIndex,
83 NSArray *allMessageFields) {
84 NSMutableArray *result = [[NSMutableArray alloc] init];
85 for (GPBFieldDescriptor *fieldDesc in allMessageFields) {
86 if (fieldDesc->description_->hasIndex == hasIndex) {
87 [result addObject:fieldDesc];
88 }
89 }
90 return result;
91 }
92
93 @implementation GPBDescriptor {
94 Class messageClass_;
95 NSArray *enums_;
96 GPBFileDescriptor *file_;
97 BOOL wireFormat_;
98 }
99
100 @synthesize messageClass = messageClass_;
101 @synthesize fields = fields_;
102 @synthesize oneofs = oneofs_;
103 @synthesize enums = enums_;
104 @synthesize extensionRanges = extensionRanges_;
105 @synthesize extensionRangesCount = extensionRangesCount_;
106 @synthesize file = file_;
107 @synthesize wireFormat = wireFormat_;
108
109 + (instancetype)
110 allocDescriptorForClass:(Class)messageClass
111 rootClass:(Class)rootClass
112 file:(GPBFileDescriptor *)file
113 fields:(GPBMessageFieldDescription *)fieldDescriptions
114 fieldCount:(NSUInteger)fieldCount
115 oneofs:(GPBMessageOneofDescription *)oneofDescriptions
116 oneofCount:(NSUInteger)oneofCount
117 enums:(GPBMessageEnumDescription *)enumDescriptions
118 enumCount:(NSUInteger)enumCount
119 ranges:(const GPBExtensionRange *)ranges
120 rangeCount:(NSUInteger)rangeCount
121 storageSize:(size_t)storageSize
122 wireFormat:(BOOL)wireFormat {
123 NSMutableArray *fields = nil;
124 NSMutableArray *oneofs = nil;
125 NSMutableArray *enums = nil;
126 NSMutableArray *extensionRanges = nil;
127 GPBFileSyntax syntax = file.syntax;
128 for (NSUInteger i = 0; i < fieldCount; ++i) {
129 if (fields == nil) {
130 fields = [[NSMutableArray alloc] initWithCapacity:fieldCount];
131 }
132 GPBFieldDescriptor *fieldDescriptor = [[GPBFieldDescriptor alloc]
133 initWithFieldDescription:&fieldDescriptions[i]
134 rootClass:rootClass
135 syntax:syntax];
136 [fields addObject:fieldDescriptor];
137 [fieldDescriptor release];
138 }
139 for (NSUInteger i = 0; i < oneofCount; ++i) {
140 if (oneofs == nil) {
141 oneofs = [[NSMutableArray alloc] initWithCapacity:oneofCount];
142 }
143 GPBMessageOneofDescription *oneofDescription = &oneofDescriptions[i];
144 NSArray *fieldsForOneof =
145 NewFieldsArrayForHasIndex(oneofDescription->index, fields);
146 GPBOneofDescriptor *oneofDescriptor =
147 [[GPBOneofDescriptor alloc] initWithOneofDescription:oneofDescription
148 fields:fieldsForOneof];
149 [oneofs addObject:oneofDescriptor];
150 [oneofDescriptor release];
151 [fieldsForOneof release];
152 }
153 for (NSUInteger i = 0; i < enumCount; ++i) {
154 if (enums == nil) {
155 enums = [[NSMutableArray alloc] initWithCapacity:enumCount];
156 }
157 GPBEnumDescriptor *enumDescriptor =
158 enumDescriptions[i].enumDescriptorFunc();
159 [enums addObject:enumDescriptor];
160 }
161
162 GPBDescriptor *descriptor = [[self alloc] initWithClass:messageClass
163 file:file
164 fields:fields
165 oneofs:oneofs
166 enums:enums
167 extensionRanges:ranges
168 extensionRangesCount:rangeCount
169 storageSize:storageSize
170 wireFormat:wireFormat];
171 [fields release];
172 [oneofs release];
173 [enums release];
174 [extensionRanges release];
175 return descriptor;
176 }
177
178 + (instancetype)
179 allocDescriptorForClass:(Class)messageClass
180 rootClass:(Class)rootClass
181 file:(GPBFileDescriptor *)file
182 fields:(GPBMessageFieldDescription *)fieldDescriptions
183 fieldCount:(NSUInteger)fieldCount
184 oneofs:(GPBMessageOneofDescription *)oneofDescriptions
185 oneofCount:(NSUInteger)oneofCount
186 enums:(GPBMessageEnumDescription *)enumDescriptions
187 enumCount:(NSUInteger)enumCount
188 ranges:(const GPBExtensionRange *)ranges
189 rangeCount:(NSUInteger)rangeCount
190 storageSize:(size_t)storageSize
191 wireFormat:(BOOL)wireFormat
192 extraTextFormatInfo:(const char *)extraTextFormatInfo {
193 GPBDescriptor *descriptor = [self allocDescriptorForClass:messageClass
194 rootClass:rootClass
195 file:file
196 fields:fieldDescriptions
197 fieldCount:fieldCount
198 oneofs:oneofDescriptions
199 oneofCount:oneofCount
200 enums:enumDescriptions
201 enumCount:enumCount
202 ranges:ranges
203 rangeCount:rangeCount
204 storageSize:storageSize
205 wireFormat:wireFormat];
206 // Extra info is a compile time option, so skip the work if not needed.
207 if (extraTextFormatInfo) {
208 NSValue *extraInfoValue = [NSValue valueWithPointer:extraTextFormatInfo];
209 for (GPBFieldDescriptor *fieldDescriptor in descriptor->fields_) {
210 if (fieldDescriptor->description_->flags & GPBFieldTextFormatNameCustom) {
211 objc_setAssociatedObject(fieldDescriptor, &kTextFormatExtraValueKey,
212 extraInfoValue,
213 OBJC_ASSOCIATION_RETAIN_NONATOMIC);
214 }
215 }
216 }
217 return descriptor;
218 }
219
220 - (instancetype)initWithClass:(Class)messageClass
221 file:(GPBFileDescriptor *)file
222 fields:(NSArray *)fields
223 oneofs:(NSArray *)oneofs
224 enums:(NSArray *)enums
225 extensionRanges:(const GPBExtensionRange *)extensionRanges
226 extensionRangesCount:(NSUInteger)extensionRangesCount
227 storageSize:(size_t)storageSize
228 wireFormat:(BOOL)wireFormat {
229 if ((self = [super init])) {
230 messageClass_ = messageClass;
231 file_ = file;
232 fields_ = [fields retain];
233 oneofs_ = [oneofs retain];
234 enums_ = [enums retain];
235 extensionRanges_ = extensionRanges;
236 extensionRangesCount_ = extensionRangesCount;
237 storageSize_ = storageSize;
238 wireFormat_ = wireFormat;
239 }
240 return self;
241 }
242
243 - (void)dealloc {
244 [fields_ release];
245 [oneofs_ release];
246 [enums_ release];
247 [super dealloc];
248 }
249
250 - (NSString *)name {
251 return NSStringFromClass(messageClass_);
252 }
253
254 - (id)copyWithZone:(NSZone *)zone {
255 #pragma unused(zone)
256 return [self retain];
257 }
258
259 - (GPBFieldDescriptor *)fieldWithNumber:(uint32_t)fieldNumber {
260 for (GPBFieldDescriptor *descriptor in fields_) {
261 if (GPBFieldNumber(descriptor) == fieldNumber) {
262 return descriptor;
263 }
264 }
265 return nil;
266 }
267
268 - (GPBFieldDescriptor *)fieldWithName:(NSString *)name {
269 for (GPBFieldDescriptor *descriptor in fields_) {
270 if ([descriptor.name isEqual:name]) {
271 return descriptor;
272 }
273 }
274 return nil;
275 }
276
277 - (GPBOneofDescriptor *)oneofWithName:(NSString *)name {
278 for (GPBOneofDescriptor *descriptor in oneofs_) {
279 if ([descriptor.name isEqual:name]) {
280 return descriptor;
281 }
282 }
283 return nil;
284 }
285
286 - (GPBEnumDescriptor *)enumWithName:(NSString *)name {
287 for (GPBEnumDescriptor *descriptor in enums_) {
288 if ([descriptor.name isEqual:name]) {
289 return descriptor;
290 }
291 }
292 return nil;
293 }
294
295 @end
296
297 @implementation GPBFileDescriptor {
298 NSString *package_;
299 GPBFileSyntax syntax_;
300 }
301
302 @synthesize package = package_;
303 @synthesize syntax = syntax_;
304
305 - (instancetype)initWithPackage:(NSString *)package
306 syntax:(GPBFileSyntax)syntax {
307 self = [super init];
308 if (self) {
309 package_ = [package copy];
310 syntax_ = syntax;
311 }
312 return self;
313 }
314
315 @end
316
317 @implementation GPBOneofDescriptor
318
319 @synthesize fields = fields_;
320
321 - (instancetype)initWithOneofDescription:
322 (GPBMessageOneofDescription *)oneofDescription
323 fields:(NSArray *)fields {
324 self = [super init];
325 if (self) {
326 NSAssert(oneofDescription->index < 0, @"Should always be <0");
327 oneofDescription_ = oneofDescription;
328 fields_ = [fields retain];
329 for (GPBFieldDescriptor *fieldDesc in fields) {
330 fieldDesc->containingOneof_ = self;
331 }
332
333 caseSel_ = SelFromStrings(NULL, oneofDescription->name, "OneOfCase", NO);
334 }
335 return self;
336 }
337
338 - (void)dealloc {
339 [fields_ release];
340 [super dealloc];
341 }
342
343 - (NSString *)name {
344 return @(oneofDescription_->name);
345 }
346
347 - (GPBFieldDescriptor *)fieldWithNumber:(uint32_t)fieldNumber {
348 for (GPBFieldDescriptor *descriptor in fields_) {
349 if (GPBFieldNumber(descriptor) == fieldNumber) {
350 return descriptor;
351 }
352 }
353 return nil;
354 }
355
356 - (GPBFieldDescriptor *)fieldWithName:(NSString *)name {
357 for (GPBFieldDescriptor *descriptor in fields_) {
358 if ([descriptor.name isEqual:name]) {
359 return descriptor;
360 }
361 }
362 return nil;
363 }
364
365 @end
366
367 uint32_t GPBFieldTag(GPBFieldDescriptor *self) {
368 GPBMessageFieldDescription *description = self->description_;
369 GPBWireFormat format;
370 if ((description->flags & GPBFieldMapKeyMask) != 0) {
371 // Maps are repeated messages on the wire.
372 format = GPBWireFormatForType(GPBDataTypeMessage, NO);
373 } else {
374 format = GPBWireFormatForType(description->dataType,
375 ((description->flags & GPBFieldPacked) != 0));
376 }
377 return GPBWireFormatMakeTag(description->number, format);
378 }
379
380 uint32_t GPBFieldAlternateTag(GPBFieldDescriptor *self) {
381 GPBMessageFieldDescription *description = self->description_;
382 NSCAssert((description->flags & GPBFieldRepeated) != 0,
383 @"Only valid on repeated fields");
384 GPBWireFormat format =
385 GPBWireFormatForType(description->dataType,
386 ((description->flags & GPBFieldPacked) == 0));
387 return GPBWireFormatMakeTag(description->number, format);
388 }
389
390 @implementation GPBFieldDescriptor {
391 GPBGenericValue defaultValue_;
392 GPBFieldOptions *fieldOptions_;
393
394 // Message ivars
395 Class msgClass_;
396
397 // Enum ivars.
398 // If protos are generated with GenerateEnumDescriptors on then it will
399 // be a enumDescriptor, otherwise it will be a enumVerifier.
400 union {
401 GPBEnumDescriptor *enumDescriptor_;
402 GPBEnumValidationFunc enumVerifier_;
403 } enumHandling_;
404 }
405
406 @synthesize fieldOptions = fieldOptions_;
407 @synthesize msgClass = msgClass_;
408 @synthesize containingOneof = containingOneof_;
409
410 - (instancetype)init {
411 // Throw an exception if people attempt to not use the designated initializer.
412 self = [super init];
413 if (self != nil) {
414 [self doesNotRecognizeSelector:_cmd];
415 self = nil;
416 }
417 return self;
418 }
419
420 - (instancetype)initWithFieldDescription:
421 (GPBMessageFieldDescription *)description
422 rootClass:(Class)rootClass
423 syntax:(GPBFileSyntax)syntax {
424 if ((self = [super init])) {
425 description_ = description;
426 getSel_ = sel_getUid(description->name);
427 setSel_ = SelFromStrings("set", description->name, NULL, YES);
428
429 GPBDataType dataType = description->dataType;
430 BOOL isMessage = GPBDataTypeIsMessage(dataType);
431 BOOL isMapOrArray = GPBFieldIsMapOrArray(self);
432
433 if (isMapOrArray) {
434 // map<>/repeated fields get a *Count property (inplace of a has*) to
435 // support checking if there are any entries without triggering
436 // autocreation.
437 hasOrCountSel_ = SelFromStrings(NULL, description->name, "_Count", NO);
438 } else {
439 // If there is a positive hasIndex, then:
440 // - All fields types for proto2 messages get has* selectors.
441 // - Only message fields for proto3 messages get has* selectors.
442 // Note: the positive check is to handle oneOfs, we can't check
443 // containingOneof_ because it isn't set until after initialization.
444 if ((description->hasIndex >= 0) &&
445 (description->hasIndex != GPBNoHasBit) &&
446 ((syntax != GPBFileSyntaxProto3) || isMessage)) {
447 hasOrCountSel_ = SelFromStrings("has", description->name, NULL, NO);
448 setHasSel_ = SelFromStrings("setHas", description->name, NULL, YES);
449 }
450 }
451
452 // Extra type specific data.
453 if (isMessage) {
454 const char *className = description->dataTypeSpecific.className;
455 msgClass_ = objc_getClass(className);
456 NSAssert(msgClass_, @"Class %s not defined", className);
457 } else if (dataType == GPBDataTypeEnum) {
458 if ((description_->flags & GPBFieldHasEnumDescriptor) != 0) {
459 enumHandling_.enumDescriptor_ =
460 description->dataTypeSpecific.enumDescFunc();
461 } else {
462 enumHandling_.enumVerifier_ =
463 description->dataTypeSpecific.enumVerifier;
464 }
465 }
466
467 // Non map<>/repeated fields can have defaults.
468 if (!isMapOrArray) {
469 defaultValue_ = description->defaultValue;
470 if (dataType == GPBDataTypeBytes) {
471 // Data stored as a length prefixed (network byte order) c-string in
472 // descriptor structure.
473 const uint8_t *bytes = (const uint8_t *)defaultValue_.valueData;
474 if (bytes) {
475 uint32_t length = *((uint32_t *)bytes);
476 length = ntohl(length);
477 bytes += sizeof(length);
478 defaultValue_.valueData =
479 [[NSData alloc] initWithBytes:bytes length:length];
480 }
481 }
482 }
483
484 // FieldOptions stored as a length prefixed (network byte order) c-escaped
485 // string in descriptor records.
486 if (description->fieldOptions) {
487 uint8_t *optionsBytes = (uint8_t *)description->fieldOptions;
488 uint32_t optionsLength = *((uint32_t *)optionsBytes);
489 optionsLength = ntohl(optionsLength);
490 if (optionsLength > 0) {
491 optionsBytes += sizeof(optionsLength);
492 NSData *optionsData = [NSData dataWithBytesNoCopy:optionsBytes
493 length:optionsLength
494 freeWhenDone:NO];
495 GPBExtensionRegistry *registry = [rootClass extensionRegistry];
496 fieldOptions_ = [[GPBFieldOptions parseFromData:optionsData
497 extensionRegistry:registry
498 error:NULL] retain];
499 }
500 }
501 }
502 return self;
503 }
504
505 - (void)dealloc {
506 if (description_->dataType == GPBDataTypeBytes &&
507 !(description_->flags & GPBFieldRepeated)) {
508 [defaultValue_.valueData release];
509 }
510 [super dealloc];
511 }
512
513 - (GPBDataType)dataType {
514 return description_->dataType;
515 }
516
517 - (BOOL)hasDefaultValue {
518 return (description_->flags & GPBFieldHasDefaultValue) != 0;
519 }
520
521 - (uint32_t)number {
522 return description_->number;
523 }
524
525 - (NSString *)name {
526 return @(description_->name);
527 }
528
529 - (BOOL)isRequired {
530 return (description_->flags & GPBFieldRequired) != 0;
531 }
532
533 - (BOOL)isOptional {
534 return (description_->flags & GPBFieldOptional) != 0;
535 }
536
537 - (GPBFieldType)fieldType {
538 GPBFieldFlags flags = description_->flags;
539 if ((flags & GPBFieldRepeated) != 0) {
540 return GPBFieldTypeRepeated;
541 } else if ((flags & GPBFieldMapKeyMask) != 0) {
542 return GPBFieldTypeMap;
543 } else {
544 return GPBFieldTypeSingle;
545 }
546 }
547
548 - (GPBDataType)mapKeyDataType {
549 switch (description_->flags & GPBFieldMapKeyMask) {
550 case GPBFieldMapKeyInt32:
551 return GPBDataTypeInt32;
552 case GPBFieldMapKeyInt64:
553 return GPBDataTypeInt64;
554 case GPBFieldMapKeyUInt32:
555 return GPBDataTypeUInt32;
556 case GPBFieldMapKeyUInt64:
557 return GPBDataTypeUInt64;
558 case GPBFieldMapKeySInt32:
559 return GPBDataTypeSInt32;
560 case GPBFieldMapKeySInt64:
561 return GPBDataTypeSInt64;
562 case GPBFieldMapKeyFixed32:
563 return GPBDataTypeFixed32;
564 case GPBFieldMapKeyFixed64:
565 return GPBDataTypeFixed64;
566 case GPBFieldMapKeySFixed32:
567 return GPBDataTypeSFixed32;
568 case GPBFieldMapKeySFixed64:
569 return GPBDataTypeSFixed64;
570 case GPBFieldMapKeyBool:
571 return GPBDataTypeBool;
572 case GPBFieldMapKeyString:
573 return GPBDataTypeString;
574
575 default:
576 NSAssert(0, @"Not a map type");
577 return GPBDataTypeInt32; // For lack of anything better.
578 }
579 }
580
581 - (BOOL)isPackable {
582 return (description_->flags & GPBFieldPacked) != 0;
583 }
584
585 - (BOOL)isValidEnumValue:(int32_t)value {
586 NSAssert(description_->dataType == GPBDataTypeEnum,
587 @"Field Must be of type GPBDataTypeEnum");
588 if (description_->flags & GPBFieldHasEnumDescriptor) {
589 return enumHandling_.enumDescriptor_.enumVerifier(value);
590 } else {
591 return enumHandling_.enumVerifier_(value);
592 }
593 }
594
595 - (GPBEnumDescriptor *)enumDescriptor {
596 if (description_->flags & GPBFieldHasEnumDescriptor) {
597 return enumHandling_.enumDescriptor_;
598 } else {
599 return nil;
600 }
601 }
602
603 - (GPBGenericValue)defaultValue {
604 // Depends on the fact that defaultValue_ is initialized either to "0/nil" or
605 // to an actual defaultValue in our initializer.
606 GPBGenericValue value = defaultValue_;
607
608 if (!(description_->flags & GPBFieldRepeated)) {
609 // We special handle data and strings. If they are nil, we replace them
610 // with empty string/empty data.
611 GPBDataType type = description_->dataType;
612 if (type == GPBDataTypeBytes && value.valueData == nil) {
613 value.valueData = GPBEmptyNSData();
614 } else if (type == GPBDataTypeString && value.valueString == nil) {
615 value.valueString = @"";
616 }
617 }
618 return value;
619 }
620
621 - (NSString *)textFormatName {
622 if ((description_->flags & GPBFieldTextFormatNameCustom) != 0) {
623 NSValue *extraInfoValue =
624 objc_getAssociatedObject(self, &kTextFormatExtraValueKey);
625 // Support can be left out at generation time.
626 if (!extraInfoValue) {
627 return nil;
628 }
629 const uint8_t *extraTextFormatInfo = [extraInfoValue pointerValue];
630 return GPBDecodeTextFormatName(extraTextFormatInfo, GPBFieldNumber(self),
631 self.name);
632 }
633
634 // The logic here has to match SetCommonFieldVariables() from
635 // objectivec_field.cc in the proto compiler.
636 NSString *name = self.name;
637 NSUInteger len = [name length];
638
639 // Remove the "_p" added to reserved names.
640 if ([name hasSuffix:@"_p"]) {
641 name = [name substringToIndex:(len - 2)];
642 len = [name length];
643 }
644
645 // Remove "Array" from the end for repeated fields.
646 if (((description_->flags & GPBFieldRepeated) != 0) &&
647 [name hasSuffix:@"Array"]) {
648 name = [name substringToIndex:(len - 5)];
649 len = [name length];
650 }
651
652 // Groups vs. other fields.
653 if (description_->dataType == GPBDataTypeGroup) {
654 // Just capitalize the first letter.
655 unichar firstChar = [name characterAtIndex:0];
656 if (firstChar >= 'a' && firstChar <= 'z') {
657 NSString *firstCharString =
658 [NSString stringWithFormat:@"%C", (unichar)(firstChar - 'a' + 'A')];
659 NSString *result =
660 [name stringByReplacingCharactersInRange:NSMakeRange(0, 1)
661 withString:firstCharString];
662 return result;
663 }
664 return name;
665
666 } else {
667 // Undo the CamelCase.
668 NSMutableString *result = [NSMutableString stringWithCapacity:len];
669 for (NSUInteger i = 0; i < len; i++) {
670 unichar c = [name characterAtIndex:i];
671 if (c >= 'A' && c <= 'Z') {
672 if (i > 0) {
673 [result appendFormat:@"_%C", (unichar)(c - 'A' + 'a')];
674 } else {
675 [result appendFormat:@"%C", c];
676 }
677 } else {
678 [result appendFormat:@"%C", c];
679 }
680 }
681 return result;
682 }
683 }
684
685 @end
686
687 @implementation GPBEnumDescriptor {
688 NSString *name_;
689 GPBMessageEnumValueDescription *valueDescriptions_;
690 NSUInteger valueDescriptionsCount_;
691 GPBEnumValidationFunc enumVerifier_;
692 const uint8_t *extraTextFormatInfo_;
693 }
694
695 @synthesize name = name_;
696 @synthesize enumVerifier = enumVerifier_;
697
698 + (instancetype)
699 allocDescriptorForName:(NSString *)name
700 values:(GPBMessageEnumValueDescription *)valueDescriptions
701 valueCount:(NSUInteger)valueCount
702 enumVerifier:(GPBEnumValidationFunc)enumVerifier {
703 GPBEnumDescriptor *descriptor = [[self alloc] initWithName:name
704 values:valueDescriptions
705 valueCount:valueCount
706 enumVerifier:enumVerifier];
707 return descriptor;
708 }
709
710 + (instancetype)
711 allocDescriptorForName:(NSString *)name
712 values:(GPBMessageEnumValueDescription *)valueDescriptions
713 valueCount:(NSUInteger)valueCount
714 enumVerifier:(GPBEnumValidationFunc)enumVerifier
715 extraTextFormatInfo:(const char *)extraTextFormatInfo {
716 // Call the common case.
717 GPBEnumDescriptor *descriptor = [self allocDescriptorForName:name
718 values:valueDescriptions
719 valueCount:valueCount
720 enumVerifier:enumVerifier];
721 // Set the extra info.
722 descriptor->extraTextFormatInfo_ = (const uint8_t *)extraTextFormatInfo;
723 return descriptor;
724 }
725
726 - (instancetype)initWithName:(NSString *)name
727 values:(GPBMessageEnumValueDescription *)valueDescriptions
728 valueCount:(NSUInteger)valueCount
729 enumVerifier:(GPBEnumValidationFunc)enumVerifier {
730 if ((self = [super init])) {
731 name_ = [name copy];
732 valueDescriptions_ = valueDescriptions;
733 valueDescriptionsCount_ = valueCount;
734 enumVerifier_ = enumVerifier;
735 }
736 return self;
737 }
738
739 - (NSString *)enumNameForValue:(int32_t)number {
740 for (NSUInteger i = 0; i < valueDescriptionsCount_; ++i) {
741 GPBMessageEnumValueDescription *scan = &valueDescriptions_[i];
742 if ((scan->number == number) && (scan->name != NULL)) {
743 NSString *fullName =
744 [NSString stringWithFormat:@"%@_%s", name_, scan->name];
745 return fullName;
746 }
747 }
748 return nil;
749 }
750
751 - (BOOL)getValue:(int32_t *)outValue forEnumName:(NSString *)name {
752 // Must have the prefix.
753 NSUInteger prefixLen = name_.length + 1;
754 if ((name.length <= prefixLen) || ![name hasPrefix:name_] ||
755 ([name characterAtIndex:prefixLen - 1] != '_')) {
756 return NO;
757 }
758
759 // Skip over the prefix.
760 const char *nameAsCStr = [name UTF8String];
761 nameAsCStr += prefixLen;
762
763 // Find it.
764 for (NSUInteger i = 0; i < valueDescriptionsCount_; ++i) {
765 GPBMessageEnumValueDescription *scan = &valueDescriptions_[i];
766 if ((scan->name != NULL) && (strcmp(nameAsCStr, scan->name) == 0)) {
767 if (outValue) {
768 *outValue = scan->number;
769 }
770 return YES;
771 }
772 }
773 return NO;
774 }
775
776 - (void)dealloc {
777 [name_ release];
778 [super dealloc];
779 }
780
781 - (NSString *)textFormatNameForValue:(int32_t)number {
782 // Find the EnumValue descriptor and its index.
783 GPBMessageEnumValueDescription *valueDescriptor = NULL;
784 NSUInteger valueDescriptorIndex;
785 for (valueDescriptorIndex = 0; valueDescriptorIndex < valueDescriptionsCount_;
786 ++valueDescriptorIndex) {
787 GPBMessageEnumValueDescription *scan =
788 &valueDescriptions_[valueDescriptorIndex];
789 if (scan->number == number) {
790 valueDescriptor = scan;
791 break;
792 }
793 }
794
795 // If we didn't find it, or names were disable at proto compile time, nothing
796 // we can do.
797 if (!valueDescriptor || !valueDescriptor->name) {
798 return nil;
799 }
800
801 NSString *result = nil;
802 // Naming adds an underscore between enum name and value name, skip that also.
803 NSString *shortName = @(valueDescriptor->name);
804
805 // See if it is in the map of special format handling.
806 if (extraTextFormatInfo_) {
807 result = GPBDecodeTextFormatName(extraTextFormatInfo_,
808 (int32_t)valueDescriptorIndex, shortName);
809 }
810 // Logic here needs to match what objectivec_enum.cc does in the proto
811 // compiler.
812 if (result == nil) {
813 NSUInteger len = [shortName length];
814 NSMutableString *worker = [NSMutableString stringWithCapacity:len];
815 for (NSUInteger i = 0; i < len; i++) {
816 unichar c = [shortName characterAtIndex:i];
817 if (i > 0 && c >= 'A' && c <= 'Z') {
818 [worker appendString:@"_"];
819 }
820 [worker appendFormat:@"%c", toupper((char)c)];
821 }
822 result = worker;
823 }
824 return result;
825 }
826
827 @end
828
829 @implementation GPBExtensionDescriptor {
830 GPBGenericValue defaultValue_;
831 }
832
833 @synthesize containingMessageClass = containingMessageClass_;
834
835 - (instancetype)initWithExtensionDescription:
836 (GPBExtensionDescription *)description {
837 if ((self = [super init])) {
838 description_ = description;
839
840 #if DEBUG
841 const char *className = description->messageOrGroupClassName;
842 if (className) {
843 NSAssert(objc_lookUpClass(className) != Nil,
844 @"Class %s not defined", className);
845 }
846 #endif
847
848 if (description->extendedClass) {
849 Class containingClass = objc_lookUpClass(description->extendedClass);
850 NSAssert(containingClass, @"Class %s not defined",
851 description->extendedClass);
852 containingMessageClass_ = containingClass;
853 }
854
855 GPBDataType type = description_->dataType;
856 if (type == GPBDataTypeBytes) {
857 // Data stored as a length prefixed c-string in descriptor records.
858 const uint8_t *bytes =
859 (const uint8_t *)description->defaultValue.valueData;
860 if (bytes) {
861 uint32_t length = *((uint32_t *)bytes);
862 // The length is stored in network byte order.
863 length = ntohl(length);
864 bytes += sizeof(length);
865 defaultValue_.valueData =
866 [[NSData alloc] initWithBytes:bytes length:length];
867 }
868 } else if (type == GPBDataTypeMessage || type == GPBDataTypeGroup) {
869 // The default is looked up in -defaultValue instead since extensions
870 // aren't common, we avoid the hit startup hit and it avoid initialization
871 // order issues.
872 } else {
873 defaultValue_ = description->defaultValue;
874 }
875 }
876 return self;
877 }
878
879 - (void)dealloc {
880 if ((description_->dataType == GPBDataTypeBytes) &&
881 !GPBExtensionIsRepeated(description_)) {
882 [defaultValue_.valueData release];
883 }
884 [super dealloc];
885 }
886
887 - (instancetype)copyWithZone:(NSZone *)zone {
888 #pragma unused(zone)
889 // Immutable.
890 return [self retain];
891 }
892
893 - (NSString *)singletonName {
894 return @(description_->singletonName);
895 }
896
897 - (const char *)singletonNameC {
898 return description_->singletonName;
899 }
900
901 - (uint32_t)fieldNumber {
902 return description_->fieldNumber;
903 }
904
905 - (GPBDataType)dataType {
906 return description_->dataType;
907 }
908
909 - (GPBWireFormat)wireType {
910 return GPBWireFormatForType(description_->dataType,
911 GPBExtensionIsPacked(description_));
912 }
913
914 - (GPBWireFormat)alternateWireType {
915 NSAssert(GPBExtensionIsRepeated(description_),
916 @"Only valid on repeated extensions");
917 return GPBWireFormatForType(description_->dataType,
918 !GPBExtensionIsPacked(description_));
919 }
920
921 - (BOOL)isRepeated {
922 return GPBExtensionIsRepeated(description_);
923 }
924
925 - (BOOL)isMap {
926 return (description_->options & GPBFieldMapKeyMask) != 0;
927 }
928
929 - (BOOL)isPackable {
930 return GPBExtensionIsPacked(description_);
931 }
932
933 - (Class)msgClass {
934 return objc_getClass(description_->messageOrGroupClassName);
935 }
936
937 - (GPBEnumDescriptor *)enumDescriptor {
938 if (description_->dataType == GPBDataTypeEnum) {
939 GPBEnumDescriptor *enumDescriptor = description_->enumDescriptorFunc();
940 return enumDescriptor;
941 }
942 return nil;
943 }
944
945 - (id)defaultValue {
946 if (GPBExtensionIsRepeated(description_)) {
947 return nil;
948 }
949
950 switch (description_->dataType) {
951 case GPBDataTypeBool:
952 return @(defaultValue_.valueBool);
953 case GPBDataTypeFloat:
954 return @(defaultValue_.valueFloat);
955 case GPBDataTypeDouble:
956 return @(defaultValue_.valueDouble);
957 case GPBDataTypeInt32:
958 case GPBDataTypeSInt32:
959 case GPBDataTypeEnum:
960 case GPBDataTypeSFixed32:
961 return @(defaultValue_.valueInt32);
962 case GPBDataTypeInt64:
963 case GPBDataTypeSInt64:
964 case GPBDataTypeSFixed64:
965 return @(defaultValue_.valueInt64);
966 case GPBDataTypeUInt32:
967 case GPBDataTypeFixed32:
968 return @(defaultValue_.valueUInt32);
969 case GPBDataTypeUInt64:
970 case GPBDataTypeFixed64:
971 return @(defaultValue_.valueUInt64);
972 case GPBDataTypeBytes:
973 // Like message fields, the default is zero length data.
974 return (defaultValue_.valueData ? defaultValue_.valueData
975 : GPBEmptyNSData());
976 case GPBDataTypeString:
977 // Like message fields, the default is zero length string.
978 return (defaultValue_.valueString ? defaultValue_.valueString : @"");
979 case GPBDataTypeGroup:
980 case GPBDataTypeMessage:
981 return nil;
982 }
983 }
984
985 - (NSComparisonResult)compareByFieldNumber:(GPBExtensionDescriptor *)other {
986 int32_t selfNumber = description_->fieldNumber;
987 int32_t otherNumber = other->description_->fieldNumber;
988 if (selfNumber < otherNumber) {
989 return NSOrderedAscending;
990 } else if (selfNumber == otherNumber) {
991 return NSOrderedSame;
992 } else {
993 return NSOrderedDescending;
994 }
995 }
996
997 @end
OLDNEW
« no previous file with comments | « third_party/protobuf/objectivec/GPBDescriptor.h ('k') | third_party/protobuf/objectivec/GPBDescriptor_PackagePrivate.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698