diff --git a/objectivec/GPBUtilities.h b/objectivec/GPBUtilities.h index ef4f8552b9..828fd16297 100644 --- a/objectivec/GPBUtilities.h +++ b/objectivec/GPBUtilities.h @@ -34,6 +34,8 @@ #import "GPBMessage.h" #import "GPBRuntimeTypes.h" +@class GPBOneofDescriptor; + CF_EXTERN_C_BEGIN NS_ASSUME_NONNULL_BEGIN @@ -92,6 +94,14 @@ BOOL GPBMessageHasFieldSet(GPBMessage *self, GPBFieldDescriptor *field); **/ void GPBClearMessageField(GPBMessage *self, GPBFieldDescriptor *field); +/** + * Clears the given onoof field for the given message. + * + * @param self The message for which to clear the field. + * @param oneof The oneof to clear. + **/ +void GPBClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof); + //%PDDM-EXPAND GPB_ACCESSORS() // This block of code is generated, do not edit it directly. // clang-format off diff --git a/objectivec/GPBUtilities.m b/objectivec/GPBUtilities.m index b89c03cbb3..ee79d00192 100644 --- a/objectivec/GPBUtilities.m +++ b/objectivec/GPBUtilities.m @@ -62,6 +62,12 @@ static GPBDataType BaseDataType(GPBDataType type) __attribute__ ((unused)); // Marked unused because currently only called from asserts/debug. static NSString *TypeToString(GPBDataType dataType) __attribute__ ((unused)); +// Helper for clearing oneofs. +static void GPBMaybeClearOneofPrivate(GPBMessage *self, + GPBOneofDescriptor *oneof, + int32_t oneofHasIndex, + uint32_t fieldNumberNotToClear); + NSData *GPBEmptyNSData(void) { static dispatch_once_t onceToken; static NSData *defaultNSData = nil; @@ -281,6 +287,16 @@ void GPBClearMessageField(GPBMessage *self, GPBFieldDescriptor *field) { GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, NO); } +void GPBClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof) { + #if defined(DEBUG) && DEBUG + NSCAssert([[self descriptor] oneofWithName:oneof.name] == oneof, + @"OneofDescriptor %@ doesn't appear to be for %@ messages.", + oneof.name, [self class]); + #endif + GPBFieldDescriptor *firstField = oneof->fields_[0]; + GPBMaybeClearOneofPrivate(self, oneof, firstField->description_->hasIndex, 0); +} + BOOL GPBGetHasIvar(GPBMessage *self, int32_t idx, uint32_t fieldNumber) { NSCAssert(self->messageStorage_ != NULL, @"%@: All messages should have storage (from init)", @@ -325,8 +341,10 @@ void GPBSetHasIvar(GPBMessage *self, int32_t idx, uint32_t fieldNumber, } } -void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof, - int32_t oneofHasIndex, uint32_t fieldNumberNotToClear) { +static void GPBMaybeClearOneofPrivate(GPBMessage *self, + GPBOneofDescriptor *oneof, + int32_t oneofHasIndex, + uint32_t fieldNumberNotToClear) { uint32_t fieldNumberSet = GPBGetHasOneof(self, oneofHasIndex); if ((fieldNumberSet == fieldNumberNotToClear) || (fieldNumberSet == 0)) { // Do nothing/nothing set in the oneof. @@ -401,7 +419,7 @@ void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof, //% GPBOneofDescriptor *oneof = field->containingOneof_; //% GPBMessageFieldDescription *fieldDesc = field->description_; //% if (oneof) { -//% GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); +//% GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number); //% } //%#if defined(DEBUG) && DEBUG //% NSCAssert(self->messageStorage_ != NULL, @@ -583,7 +601,7 @@ void GPBSetRetainedObjectIvarWithFieldPrivate(GPBMessage *self, // oneof. GPBOneofDescriptor *oneof = field->containingOneof_; if (oneof) { - GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); + GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number); } // Clear "has" if they are being set to nil. BOOL setHasValue = (value != nil); @@ -778,7 +796,7 @@ void GPBSetBoolIvarWithFieldPrivate(GPBMessage *self, GPBMessageFieldDescription *fieldDesc = field->description_; GPBOneofDescriptor *oneof = field->containingOneof_; if (oneof) { - GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); + GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number); } // Bools are stored in the has bits to avoid needing explicit space in the @@ -846,7 +864,7 @@ void GPBSetInt32IvarWithFieldPrivate(GPBMessage *self, GPBOneofDescriptor *oneof = field->containingOneof_; GPBMessageFieldDescription *fieldDesc = field->description_; if (oneof) { - GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); + GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number); } #if defined(DEBUG) && DEBUG NSCAssert(self->messageStorage_ != NULL, @@ -919,7 +937,7 @@ void GPBSetUInt32IvarWithFieldPrivate(GPBMessage *self, GPBOneofDescriptor *oneof = field->containingOneof_; GPBMessageFieldDescription *fieldDesc = field->description_; if (oneof) { - GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); + GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number); } #if defined(DEBUG) && DEBUG NSCAssert(self->messageStorage_ != NULL, @@ -992,7 +1010,7 @@ void GPBSetInt64IvarWithFieldPrivate(GPBMessage *self, GPBOneofDescriptor *oneof = field->containingOneof_; GPBMessageFieldDescription *fieldDesc = field->description_; if (oneof) { - GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); + GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number); } #if defined(DEBUG) && DEBUG NSCAssert(self->messageStorage_ != NULL, @@ -1065,7 +1083,7 @@ void GPBSetUInt64IvarWithFieldPrivate(GPBMessage *self, GPBOneofDescriptor *oneof = field->containingOneof_; GPBMessageFieldDescription *fieldDesc = field->description_; if (oneof) { - GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); + GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number); } #if defined(DEBUG) && DEBUG NSCAssert(self->messageStorage_ != NULL, @@ -1138,7 +1156,7 @@ void GPBSetFloatIvarWithFieldPrivate(GPBMessage *self, GPBOneofDescriptor *oneof = field->containingOneof_; GPBMessageFieldDescription *fieldDesc = field->description_; if (oneof) { - GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); + GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number); } #if defined(DEBUG) && DEBUG NSCAssert(self->messageStorage_ != NULL, @@ -1211,7 +1229,7 @@ void GPBSetDoubleIvarWithFieldPrivate(GPBMessage *self, GPBOneofDescriptor *oneof = field->containingOneof_; GPBMessageFieldDescription *fieldDesc = field->description_; if (oneof) { - GPBMaybeClearOneof(self, oneof, fieldDesc->hasIndex, fieldDesc->number); + GPBMaybeClearOneofPrivate(self, oneof, fieldDesc->hasIndex, fieldDesc->number); } #if defined(DEBUG) && DEBUG NSCAssert(self->messageStorage_ != NULL, @@ -2221,8 +2239,6 @@ NSString *GPBDecodeTextFormatName(const uint8_t *decodeData, int32_t key, return result; } -#pragma clang diagnostic pop - #pragma mark Legacy methods old generated code calls // Shim from the older generated code into the runtime. @@ -2234,6 +2250,23 @@ void GPBSetInt32IvarWithFieldInternal(GPBMessage *self, GPBSetMessageInt32Field(self, field, value); } +void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof, + int32_t oneofHasIndex, uint32_t fieldNumberNotToClear) { +#pragma unused(fieldNumberNotToClear) + #if defined(DEBUG) && DEBUG + NSCAssert([[self descriptor] oneofWithName:oneof.name] == oneof, + @"OneofDescriptor %@ doesn't appear to be for %@ messages.", + oneof.name, [self class]); + GPBFieldDescriptor *firstField = oneof->fields_[0]; + NSCAssert(firstField->description_->hasIndex == oneofHasIndex, + @"Internal error, oneofHasIndex (%d) doesn't match (%d).", + firstField->description_->hasIndex, oneofHasIndex); + #endif + GPBMaybeClearOneofPrivate(self, oneof, oneofHasIndex, 0); +} + +#pragma clang diagnostic pop + #pragma mark Misc Helpers BOOL GPBClassHasSel(Class aClass, SEL sel) { diff --git a/objectivec/GPBUtilities_PackagePrivate.h b/objectivec/GPBUtilities_PackagePrivate.h index 280b6deb00..9c29c39c0b 100644 --- a/objectivec/GPBUtilities_PackagePrivate.h +++ b/objectivec/GPBUtilities_PackagePrivate.h @@ -207,9 +207,6 @@ GPBGetHasIvarField(GPBMessage *self, GPBFieldDescriptor *field) { return GPBGetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number); } -void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof, - int32_t oneofHasIndex, uint32_t fieldNumberNotToClear); - #pragma clang diagnostic pop //%PDDM-DEFINE GPB_IVAR_SET_DECL(NAME, TYPE) @@ -313,11 +310,13 @@ NSString *GPBDecodeTextFormatName(const uint8_t *decodeData, int32_t key, NSString *inputString); -// Shim from the older generated code into the runtime. +// Shims from the older generated code into the runtime. void GPBSetInt32IvarWithFieldInternal(GPBMessage *self, GPBFieldDescriptor *field, int32_t value, GPBFileSyntax syntax); +void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof, + int32_t oneofHasIndex, uint32_t fieldNumberNotToClear); // A series of selectors that are used solely to get @encoding values // for them by the dynamic protobuf runtime code. See