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 17 matching lines...) Expand all Loading... |
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 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. | 29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
30 | 30 |
31 #import "GPBMessage_PackagePrivate.h" | 31 #import "GPBMessage_PackagePrivate.h" |
32 | 32 |
33 #import <objc/runtime.h> | 33 #import <objc/runtime.h> |
34 #import <objc/message.h> | 34 #import <objc/message.h> |
35 | 35 |
36 #import "GPBArray_PackagePrivate.h" | 36 #import "GPBArray_PackagePrivate.h" |
37 #import "GPBCodedInputStream_PackagePrivate.h" | 37 #import "GPBCodedInputStream_PackagePrivate.h" |
38 #import "GPBCodedOutputStream.h" | 38 #import "GPBCodedOutputStream_PackagePrivate.h" |
39 #import "GPBDescriptor_PackagePrivate.h" | 39 #import "GPBDescriptor_PackagePrivate.h" |
40 #import "GPBDictionary_PackagePrivate.h" | 40 #import "GPBDictionary_PackagePrivate.h" |
41 #import "GPBExtensionInternals.h" | 41 #import "GPBExtensionInternals.h" |
42 #import "GPBExtensionRegistry.h" | 42 #import "GPBExtensionRegistry.h" |
43 #import "GPBRootObject_PackagePrivate.h" | 43 #import "GPBRootObject_PackagePrivate.h" |
44 #import "GPBUnknownFieldSet_PackagePrivate.h" | 44 #import "GPBUnknownFieldSet_PackagePrivate.h" |
45 #import "GPBUtilities_PackagePrivate.h" | 45 #import "GPBUtilities_PackagePrivate.h" |
46 | 46 |
47 NSString *const GPBMessageErrorDomain = | 47 NSString *const GPBMessageErrorDomain = |
48 GPBNSStringifySymbol(GPBMessageErrorDomain); | 48 GPBNSStringifySymbol(GPBMessageErrorDomain); |
49 | 49 |
50 #ifdef DEBUG | 50 #ifdef DEBUG |
51 NSString *const GPBExceptionMessageKey = | 51 NSString *const GPBExceptionMessageKey = |
52 GPBNSStringifySymbol(GPBExceptionMessage); | 52 GPBNSStringifySymbol(GPBExceptionMessage); |
53 #endif // DEBUG | 53 #endif // DEBUG |
54 | 54 |
55 static NSString *const kGPBDataCoderKey = @"GPBData"; | 55 static NSString *const kGPBDataCoderKey = @"GPBData"; |
56 | 56 |
57 #ifndef _GPBCompileAssert | |
58 #if __has_feature(c_static_assert) || __has_extension(c_static_assert) | |
59 #define _GPBCompileAssert(test, msg) _Static_assert((test), #msg) | |
60 #else | |
61 // Pre-Xcode 7 support. | |
62 #define _GPBCompileAssertSymbolInner(line, msg) _GPBCompileAssert ## line ##
__ ## msg | |
63 #define _GPBCompileAssertSymbol(line, msg) _GPBCompileAssertSymbolInner(line
, msg) | |
64 #define _GPBCompileAssert(test, msg) \ | |
65 typedef char _GPBCompileAssertSymbol(__LINE__, msg) [ ((test) ? 1 : -1)
] | |
66 #endif // __has_feature(c_static_assert) || __has_extension(c_static_assert) | |
67 #endif // _GPBCompileAssert | |
68 | |
69 // | 57 // |
70 // PLEASE REMEMBER: | 58 // PLEASE REMEMBER: |
71 // | 59 // |
72 // This is the base class for *all* messages generated, so any selector defined, | 60 // This is the base class for *all* messages generated, so any selector defined, |
73 // *public* or *private* could end up colliding with a proto message field. So | 61 // *public* or *private* could end up colliding with a proto message field. So |
74 // avoid using selectors that could match a property, use C functions to hide | 62 // avoid using selectors that could match a property, use C functions to hide |
75 // them, etc. | 63 // them, etc. |
76 // | 64 // |
77 | 65 |
78 @interface GPBMessage () { | 66 @interface GPBMessage () { |
(...skipping 482 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
561 } | 549 } |
562 return array; | 550 return array; |
563 } | 551 } |
564 | 552 |
565 // This is like GPBGetObjectIvarWithField(), but for arrays, it should | 553 // This is like GPBGetObjectIvarWithField(), but for arrays, it should |
566 // only be used to wire the method into the class. | 554 // only be used to wire the method into the class. |
567 static id GetArrayIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) { | 555 static id GetArrayIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) { |
568 id array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); | 556 id array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
569 if (!array) { | 557 if (!array) { |
570 // Check again after getting the lock. | 558 // Check again after getting the lock. |
| 559 GPBPrepareReadOnlySemaphore(self); |
571 dispatch_semaphore_wait(self->readOnlySemaphore_, DISPATCH_TIME_FOREVER); | 560 dispatch_semaphore_wait(self->readOnlySemaphore_, DISPATCH_TIME_FOREVER); |
572 array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); | 561 array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
573 if (!array) { | 562 if (!array) { |
574 array = CreateArrayForField(field, self); | 563 array = CreateArrayForField(field, self); |
575 GPBSetAutocreatedRetainedObjectIvarWithField(self, field, array); | 564 GPBSetAutocreatedRetainedObjectIvarWithField(self, field, array); |
576 } | 565 } |
577 dispatch_semaphore_signal(self->readOnlySemaphore_); | 566 dispatch_semaphore_signal(self->readOnlySemaphore_); |
578 } | 567 } |
579 return array; | 568 return array; |
580 } | 569 } |
(...skipping 10 matching lines...) Expand all Loading... |
591 } | 580 } |
592 return dict; | 581 return dict; |
593 } | 582 } |
594 | 583 |
595 // This is like GPBGetObjectIvarWithField(), but for maps, it should | 584 // This is like GPBGetObjectIvarWithField(), but for maps, it should |
596 // only be used to wire the method into the class. | 585 // only be used to wire the method into the class. |
597 static id GetMapIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) { | 586 static id GetMapIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) { |
598 id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); | 587 id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
599 if (!dict) { | 588 if (!dict) { |
600 // Check again after getting the lock. | 589 // Check again after getting the lock. |
| 590 GPBPrepareReadOnlySemaphore(self); |
601 dispatch_semaphore_wait(self->readOnlySemaphore_, DISPATCH_TIME_FOREVER); | 591 dispatch_semaphore_wait(self->readOnlySemaphore_, DISPATCH_TIME_FOREVER); |
602 dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); | 592 dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); |
603 if (!dict) { | 593 if (!dict) { |
604 dict = CreateMapForField(field, self); | 594 dict = CreateMapForField(field, self); |
605 GPBSetAutocreatedRetainedObjectIvarWithField(self, field, dict); | 595 GPBSetAutocreatedRetainedObjectIvarWithField(self, field, dict); |
606 } | 596 } |
607 dispatch_semaphore_signal(self->readOnlySemaphore_); | 597 dispatch_semaphore_signal(self->readOnlySemaphore_); |
608 } | 598 } |
609 return dict; | 599 return dict; |
610 } | 600 } |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
782 // it supports unknowns/etc. | 772 // it supports unknowns/etc. |
783 fileDescriptor = | 773 fileDescriptor = |
784 [[GPBFileDescriptor alloc] initWithPackage:@"internal" | 774 [[GPBFileDescriptor alloc] initWithPackage:@"internal" |
785 syntax:GPBFileSyntaxProto2]; | 775 syntax:GPBFileSyntaxProto2]; |
786 | 776 |
787 descriptor = [GPBDescriptor allocDescriptorForClass:[GPBMessage class] | 777 descriptor = [GPBDescriptor allocDescriptorForClass:[GPBMessage class] |
788 rootClass:Nil | 778 rootClass:Nil |
789 file:fileDescriptor | 779 file:fileDescriptor |
790 fields:NULL | 780 fields:NULL |
791 fieldCount:0 | 781 fieldCount:0 |
792 oneofs:NULL | |
793 oneofCount:0 | |
794 enums:NULL | |
795 enumCount:0 | |
796 ranges:NULL | |
797 rangeCount:0 | |
798 storageSize:0 | 782 storageSize:0 |
799 wireFormat:NO]; | 783 flags:0]; |
800 } | 784 } |
801 return descriptor; | 785 return descriptor; |
802 } | 786 } |
803 | 787 |
804 + (instancetype)message { | 788 + (instancetype)message { |
805 return [[[self alloc] init] autorelease]; | 789 return [[[self alloc] init] autorelease]; |
806 } | 790 } |
807 | 791 |
808 - (instancetype)init { | 792 - (instancetype)init { |
809 if ((self = [super init])) { | 793 if ((self = [super init])) { |
810 messageStorage_ = (GPBMessage_StoragePtr)( | 794 messageStorage_ = (GPBMessage_StoragePtr)( |
811 ((uint8_t *)self) + class_getInstanceSize([self class])); | 795 ((uint8_t *)self) + class_getInstanceSize([self class])); |
812 | |
813 readOnlySemaphore_ = dispatch_semaphore_create(1); | |
814 } | 796 } |
815 | 797 |
816 return self; | 798 return self; |
817 } | 799 } |
818 | 800 |
819 - (instancetype)initWithData:(NSData *)data error:(NSError **)errorPtr { | 801 - (instancetype)initWithData:(NSData *)data error:(NSError **)errorPtr { |
820 return [self initWithData:data extensionRegistry:nil error:errorPtr]; | 802 return [self initWithData:data extensionRegistry:nil error:errorPtr]; |
821 } | 803 } |
822 | 804 |
823 - (instancetype)initWithData:(NSData *)data | 805 - (instancetype)initWithData:(NSData *)data |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
879 } | 861 } |
880 } | 862 } |
881 #endif | 863 #endif |
882 } | 864 } |
883 return self; | 865 return self; |
884 } | 866 } |
885 | 867 |
886 - (void)dealloc { | 868 - (void)dealloc { |
887 [self internalClear:NO]; | 869 [self internalClear:NO]; |
888 NSCAssert(!autocreator_, @"Autocreator was not cleared before dealloc."); | 870 NSCAssert(!autocreator_, @"Autocreator was not cleared before dealloc."); |
| 871 if (readOnlySemaphore_) { |
| 872 dispatch_release(readOnlySemaphore_); |
| 873 } |
889 [super dealloc]; | 874 [super dealloc]; |
890 } | 875 } |
891 | 876 |
892 - (void)copyFieldsInto:(GPBMessage *)message | 877 - (void)copyFieldsInto:(GPBMessage *)message |
893 zone:(NSZone *)zone | 878 zone:(NSZone *)zone |
894 descriptor:(GPBDescriptor *)descriptor { | 879 descriptor:(GPBDescriptor *)descriptor { |
895 // Copy all the storage... | 880 // Copy all the storage... |
896 memcpy(message->messageStorage_, messageStorage_, descriptor->storageSize_); | 881 memcpy(message->messageStorage_, messageStorage_, descriptor->storageSize_); |
897 | 882 |
898 GPBFileSyntax syntax = descriptor.file.syntax; | 883 GPBFileSyntax syntax = descriptor.file.syntax; |
(...skipping 817 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1716 // No default for repeated. | 1701 // No default for repeated. |
1717 if (extension.isRepeated) { | 1702 if (extension.isRepeated) { |
1718 return nil; | 1703 return nil; |
1719 } | 1704 } |
1720 // Non messages get their default. | 1705 // Non messages get their default. |
1721 if (!GPBExtensionIsMessage(extension)) { | 1706 if (!GPBExtensionIsMessage(extension)) { |
1722 return extension.defaultValue; | 1707 return extension.defaultValue; |
1723 } | 1708 } |
1724 | 1709 |
1725 // Check for an autocreated value. | 1710 // Check for an autocreated value. |
| 1711 GPBPrepareReadOnlySemaphore(self); |
1726 dispatch_semaphore_wait(readOnlySemaphore_, DISPATCH_TIME_FOREVER); | 1712 dispatch_semaphore_wait(readOnlySemaphore_, DISPATCH_TIME_FOREVER); |
1727 value = [autocreatedExtensionMap_ objectForKey:extension]; | 1713 value = [autocreatedExtensionMap_ objectForKey:extension]; |
1728 if (!value) { | 1714 if (!value) { |
1729 // Auto create the message extensions to match normal fields. | 1715 // Auto create the message extensions to match normal fields. |
1730 value = CreateMessageWithAutocreatorForExtension(extension.msgClass, self, | 1716 value = CreateMessageWithAutocreatorForExtension(extension.msgClass, self, |
1731 extension); | 1717 extension); |
1732 | 1718 |
1733 if (autocreatedExtensionMap_ == nil) { | 1719 if (autocreatedExtensionMap_ == nil) { |
1734 autocreatedExtensionMap_ = [[NSMutableDictionary alloc] init]; | 1720 autocreatedExtensionMap_ = [[NSMutableDictionary alloc] init]; |
1735 } | 1721 } |
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1927 error:(NSError **)errorPtr { | 1913 error:(NSError **)errorPtr { |
1928 GPBMessage *message = [[[self alloc] init] autorelease]; | 1914 GPBMessage *message = [[[self alloc] init] autorelease]; |
1929 @try { | 1915 @try { |
1930 [message mergeDelimitedFromCodedInputStream:input | 1916 [message mergeDelimitedFromCodedInputStream:input |
1931 extensionRegistry:extensionRegistry]; | 1917 extensionRegistry:extensionRegistry]; |
1932 if (errorPtr) { | 1918 if (errorPtr) { |
1933 *errorPtr = nil; | 1919 *errorPtr = nil; |
1934 } | 1920 } |
1935 } | 1921 } |
1936 @catch (NSException *exception) { | 1922 @catch (NSException *exception) { |
1937 [message release]; | |
1938 message = nil; | 1923 message = nil; |
1939 if (errorPtr) { | 1924 if (errorPtr) { |
1940 *errorPtr = MessageErrorWithReason(GPBMessageErrorCodeMalformedData, | 1925 *errorPtr = MessageErrorWithReason(GPBMessageErrorCodeMalformedData, |
1941 exception.reason); | 1926 exception.reason); |
1942 } | 1927 } |
1943 } | 1928 } |
1944 #ifdef DEBUG | 1929 #ifdef DEBUG |
1945 if (message && !message.initialized) { | 1930 if (message && !message.initialized) { |
1946 [message release]; | |
1947 message = nil; | 1931 message = nil; |
1948 if (errorPtr) { | 1932 if (errorPtr) { |
1949 *errorPtr = MessageError(GPBMessageErrorCodeMissingRequiredField, nil); | 1933 *errorPtr = MessageError(GPBMessageErrorCodeMissingRequiredField, nil); |
1950 } | 1934 } |
1951 } | 1935 } |
1952 #endif | 1936 #endif |
1953 return message; | 1937 return message; |
1954 } | 1938 } |
1955 | 1939 |
1956 #pragma mark - Unknown Field Support | 1940 #pragma mark - Unknown Field Support |
(...skipping 655 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2612 } | 2596 } |
2613 if (!selfHas) { | 2597 if (!selfHas) { |
2614 // Same has values, was no, nothing else to check for this field. | 2598 // Same has values, was no, nothing else to check for this field. |
2615 continue; | 2599 continue; |
2616 } | 2600 } |
2617 // Now compare the values. | 2601 // Now compare the values. |
2618 GPBDataType fieldDataType = GPBGetFieldDataType(field); | 2602 GPBDataType fieldDataType = GPBGetFieldDataType(field); |
2619 size_t fieldOffset = field->description_->offset; | 2603 size_t fieldOffset = field->description_->offset; |
2620 switch (fieldDataType) { | 2604 switch (fieldDataType) { |
2621 case GPBDataTypeBool: { | 2605 case GPBDataTypeBool: { |
2622 BOOL *selfValPtr = (BOOL *)&selfStorage[fieldOffset]; | 2606 // Bools are stored in has_bits to avoid needing explicit space in |
2623 BOOL *otherValPtr = (BOOL *)&otherStorage[fieldOffset]; | 2607 // the storage structure. |
2624 if (*selfValPtr != *otherValPtr) { | 2608 // (the field number passed to the HasIvar helper doesn't really |
| 2609 // matter since the offset is never negative) |
| 2610 BOOL selfValue = GPBGetHasIvar(self, (int32_t)(fieldOffset), 0); |
| 2611 BOOL otherValue = GPBGetHasIvar(other, (int32_t)(fieldOffset), 0); |
| 2612 if (selfValue != otherValue) { |
2625 return NO; | 2613 return NO; |
2626 } | 2614 } |
2627 break; | 2615 break; |
2628 } | 2616 } |
2629 case GPBDataTypeSFixed32: | 2617 case GPBDataTypeSFixed32: |
2630 case GPBDataTypeInt32: | 2618 case GPBDataTypeInt32: |
2631 case GPBDataTypeSInt32: | 2619 case GPBDataTypeSInt32: |
2632 case GPBDataTypeEnum: | 2620 case GPBDataTypeEnum: |
2633 case GPBDataTypeFixed32: | 2621 case GPBDataTypeFixed32: |
2634 case GPBDataTypeUInt32: | 2622 case GPBDataTypeUInt32: |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2723 result = prime * result + count; | 2711 result = prime * result + count; |
2724 } | 2712 } |
2725 } else if (GPBGetHasIvarField(self, field)) { | 2713 } else if (GPBGetHasIvarField(self, field)) { |
2726 // Just using the field number seemed simple/fast, but then a small | 2714 // Just using the field number seemed simple/fast, but then a small |
2727 // message class where all the same fields are always set (to different | 2715 // message class where all the same fields are always set (to different |
2728 // things would end up all with the same hash, so pull in some data). | 2716 // things would end up all with the same hash, so pull in some data). |
2729 GPBDataType fieldDataType = GPBGetFieldDataType(field); | 2717 GPBDataType fieldDataType = GPBGetFieldDataType(field); |
2730 size_t fieldOffset = field->description_->offset; | 2718 size_t fieldOffset = field->description_->offset; |
2731 switch (fieldDataType) { | 2719 switch (fieldDataType) { |
2732 case GPBDataTypeBool: { | 2720 case GPBDataTypeBool: { |
2733 BOOL *valPtr = (BOOL *)&storage[fieldOffset]; | 2721 // Bools are stored in has_bits to avoid needing explicit space in |
2734 result = prime * result + *valPtr; | 2722 // the storage structure. |
| 2723 // (the field number passed to the HasIvar helper doesn't really |
| 2724 // matter since the offset is never negative) |
| 2725 BOOL value = GPBGetHasIvar(self, (int32_t)(fieldOffset), 0); |
| 2726 result = prime * result + value; |
2735 break; | 2727 break; |
2736 } | 2728 } |
2737 case GPBDataTypeSFixed32: | 2729 case GPBDataTypeSFixed32: |
2738 case GPBDataTypeInt32: | 2730 case GPBDataTypeInt32: |
2739 case GPBDataTypeSInt32: | 2731 case GPBDataTypeSInt32: |
2740 case GPBDataTypeEnum: | 2732 case GPBDataTypeEnum: |
2741 case GPBDataTypeFixed32: | 2733 case GPBDataTypeFixed32: |
2742 case GPBDataTypeUInt32: | 2734 case GPBDataTypeUInt32: |
2743 case GPBDataTypeFloat: { | 2735 case GPBDataTypeFloat: { |
2744 _GPBCompileAssert(sizeof(float) == sizeof(uint32_t), float_not_32_bits
); | 2736 _GPBCompileAssert(sizeof(float) == sizeof(uint32_t), float_not_32_bits
); |
(...skipping 343 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3088 [obj class], | 3080 [obj class], |
3089 NSStringFromSelector(field->setHasSel_)]; | 3081 NSStringFromSelector(field->setHasSel_)]; |
3090 } | 3082 } |
3091 GPBClearMessageField(obj, field); | 3083 GPBClearMessageField(obj, field); |
3092 }); | 3084 }); |
3093 result.encodingSelector = @selector(setBool:); | 3085 result.encodingSelector = @selector(setBool:); |
3094 break; | 3086 break; |
3095 } else { | 3087 } else { |
3096 GPBOneofDescriptor *oneof = field->containingOneof_; | 3088 GPBOneofDescriptor *oneof = field->containingOneof_; |
3097 if (oneof && (sel == oneof->caseSel_)) { | 3089 if (oneof && (sel == oneof->caseSel_)) { |
3098 int32_t index = oneof->oneofDescription_->index; | 3090 int32_t index = GPBFieldHasIndex(field); |
3099 result.impToAdd = imp_implementationWithBlock(^(id obj) { | 3091 result.impToAdd = imp_implementationWithBlock(^(id obj) { |
3100 return GPBGetHasOneof(obj, index); | 3092 return GPBGetHasOneof(obj, index); |
3101 }); | 3093 }); |
3102 result.encodingSelector = @selector(getEnum); | 3094 result.encodingSelector = @selector(getEnum); |
3103 break; | 3095 break; |
3104 } | 3096 } |
3105 } | 3097 } |
3106 } else { | 3098 } else { |
3107 // map<>/repeated fields. | 3099 // map<>/repeated fields. |
3108 if (sel == field->getSel_) { | 3100 if (sel == field->getSel_) { |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3183 } | 3175 } |
3184 | 3176 |
3185 #pragma mark - KVC Support | 3177 #pragma mark - KVC Support |
3186 | 3178 |
3187 + (BOOL)accessInstanceVariablesDirectly { | 3179 + (BOOL)accessInstanceVariablesDirectly { |
3188 // Make sure KVC doesn't use instance variables. | 3180 // Make sure KVC doesn't use instance variables. |
3189 return NO; | 3181 return NO; |
3190 } | 3182 } |
3191 | 3183 |
3192 @end | 3184 @end |
OLD | NEW |