Browse Source

[ObjC] Update oneof clearing internals.

- Add/document an public api for clearing oneofs.
- Move the current library internals to a new api and keep a shim for old
  generated code.
Thomas Van Lenten 5 years ago
parent
commit
3c8e959b60
3 changed files with 59 additions and 17 deletions
  1. 10 0
      objectivec/GPBUtilities.h
  2. 46 13
      objectivec/GPBUtilities.m
  3. 3 4
      objectivec/GPBUtilities_PackagePrivate.h

+ 10 - 0
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

+ 46 - 13
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) {

+ 3 - 4
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