upb: implement _upb_Message_ClearOneofCase()

PiperOrigin-RevId: 595018281
pull/15181/head
Eric Salo 1 year ago committed by Copybara-Service
parent de5ea1e6a4
commit 4ba7d27201
  1. 1
      upb/message/BUILD
  2. 117
      upb/message/internal/accessors.h
  3. 9
      upb/mini_table/internal/field.h
  4. 10
      upb/wire/decode.c
  5. 2
      upb/wire/encode.c

@ -72,6 +72,7 @@ cc_library(
"//upb:port", "//upb:port",
"//upb/base:internal", "//upb/base:internal",
"//upb/hash", "//upb/hash",
"//upb/mini_table:internal",
], ],
) )

@ -20,6 +20,7 @@
#include "upb/message/internal/tagged_ptr.h" #include "upb/message/internal/tagged_ptr.h"
#include "upb/mini_table/extension.h" #include "upb/mini_table/extension.h"
#include "upb/mini_table/field.h" #include "upb/mini_table/field.h"
#include "upb/mini_table/internal/field.h"
// Must be last. // Must be last.
#include "upb/port/def.inc" #include "upb/port/def.inc"
@ -84,41 +85,74 @@ UPB_INLINE uint32_t* UPB_PRIVATE(_upb_Message_OneofCasePtr)(
UPB_INLINE uint32_t UPB_PRIVATE(_upb_Message_GetOneofCase)( UPB_INLINE uint32_t UPB_PRIVATE(_upb_Message_GetOneofCase)(
const struct upb_Message* msg, const upb_MiniTableField* f) { const struct upb_Message* msg, const upb_MiniTableField* f) {
return *UPB_PRIVATE(_upb_Message_OneofCasePtr)((struct upb_Message*)msg, f); const uint32_t* ptr =
UPB_PRIVATE(_upb_Message_OneofCasePtr)((struct upb_Message*)msg, f);
return *ptr;
} }
UPB_INLINE void UPB_PRIVATE(_upb_Message_SetOneofCase)( UPB_INLINE void UPB_PRIVATE(_upb_Message_SetOneofCase)(
struct upb_Message* msg, const upb_MiniTableField* f) { struct upb_Message* msg, const upb_MiniTableField* f) {
*UPB_PRIVATE(_upb_Message_OneofCasePtr)(msg, f) = uint32_t* ptr = UPB_PRIVATE(_upb_Message_OneofCasePtr)(msg, f);
upb_MiniTableField_Number(f);
*ptr = upb_MiniTableField_Number(f);
} }
// TODO: implement _upb_Message_ClearOneofCase() // Returns true if the given field is the current oneof case.
// Does nothing if it is not the current oneof case.
UPB_INLINE bool UPB_PRIVATE(_upb_Message_ClearOneofCase)(
struct upb_Message* msg, const upb_MiniTableField* f) {
uint32_t* ptr = UPB_PRIVATE(_upb_Message_OneofCasePtr)(msg, f);
if (*ptr != upb_MiniTableField_Number(f)) return false;
*ptr = 0;
return true;
}
// LINT.ThenChange(GoogleInternalName2) // LINT.ThenChange(GoogleInternalName2)
UPB_INLINE void* _upb_MiniTableField_GetPtr(struct upb_Message* msg, UPB_INLINE void* UPB_PRIVATE(_upb_Message_DataPtr)(
const upb_MiniTableField* field) { struct upb_Message* msg, const upb_MiniTableField* f) {
return (char*)msg + field->UPB_ONLYBITS(offset); return (char*)msg + f->UPB_ONLYBITS(offset);
} }
UPB_INLINE const void* _upb_MiniTableField_GetConstPtr( UPB_INLINE const void* UPB_PRIVATE(_upb_Message_ConstDataPtr)(
const struct upb_Message* msg, const upb_MiniTableField* field) { const struct upb_Message* msg, const upb_MiniTableField* f) {
return (char*)msg + field->UPB_ONLYBITS(offset); return (const char*)msg + f->UPB_ONLYBITS(offset);
} }
UPB_INLINE void UPB_PRIVATE(_upb_Message_SetPresence)( UPB_INLINE void UPB_PRIVATE(_upb_Message_SetPresence)(
struct upb_Message* msg, const upb_MiniTableField* field) { struct upb_Message* msg, const upb_MiniTableField* f) {
if (field->presence > 0) { if (UPB_PRIVATE(_upb_MiniTableField_HasHasbit)(f)) {
UPB_PRIVATE(_upb_Message_SetHasbit)(msg, field); UPB_PRIVATE(_upb_Message_SetHasbit)(msg, f);
} else if (upb_MiniTableField_IsInOneof(field)) { } else if (upb_MiniTableField_IsInOneof(f)) {
UPB_PRIVATE(_upb_Message_SetOneofCase)(msg, field); UPB_PRIVATE(_upb_Message_SetOneofCase)(msg, f);
} }
} }
UPB_INLINE void UPB_PRIVATE(_upb_MiniTableField_DataCopy)(
const upb_MiniTableField* f, void* to, const void* from) {
switch (UPB_PRIVATE(_upb_MiniTableField_GetRep)(f)) {
case kUpb_FieldRep_1Byte:
memcpy(to, from, 1);
return;
case kUpb_FieldRep_4Byte:
memcpy(to, from, 4);
return;
case kUpb_FieldRep_8Byte:
memcpy(to, from, 8);
return;
case kUpb_FieldRep_StringView: {
memcpy(to, from, sizeof(upb_StringView));
return;
}
}
UPB_UNREACHABLE();
}
UPB_INLINE bool UPB_PRIVATE(_upb_MiniTableField_DataEquals)( UPB_INLINE bool UPB_PRIVATE(_upb_MiniTableField_DataEquals)(
const upb_MiniTableField* field, const void* a, const void* b) { const upb_MiniTableField* f, const void* a, const void* b) {
switch (UPB_PRIVATE(_upb_MiniTableField_GetRep)(field)) { switch (UPB_PRIVATE(_upb_MiniTableField_GetRep)(f)) {
case kUpb_FieldRep_1Byte: case kUpb_FieldRep_1Byte:
return memcmp(a, b, 1) == 0; return memcmp(a, b, 1) == 0;
case kUpb_FieldRep_4Byte: case kUpb_FieldRep_4Byte:
@ -134,30 +168,16 @@ UPB_INLINE bool UPB_PRIVATE(_upb_MiniTableField_DataEquals)(
UPB_UNREACHABLE(); UPB_UNREACHABLE();
} }
UPB_INLINE bool UPB_PRIVATE(_upb_MiniTableField_DataIsZero)( UPB_INLINE void UPB_PRIVATE(_upb_MiniTableField_DataClear)(
const upb_MiniTableField* field, const void* val) { const upb_MiniTableField* f, void* val) {
const char zero[16] = {0}; const char zero[16] = {0};
return UPB_PRIVATE(_upb_MiniTableField_DataEquals)(field, val, zero); return UPB_PRIVATE(_upb_MiniTableField_DataCopy)(f, val, zero);
} }
UPB_INLINE void UPB_PRIVATE(_upb_MiniTableField_DataCopy)( UPB_INLINE bool UPB_PRIVATE(_upb_MiniTableField_DataIsZero)(
const upb_MiniTableField* field, void* to, const void* from) { const upb_MiniTableField* f, const void* val) {
switch (UPB_PRIVATE(_upb_MiniTableField_GetRep)(field)) { const char zero[16] = {0};
case kUpb_FieldRep_1Byte: return UPB_PRIVATE(_upb_MiniTableField_DataEquals)(f, val, zero);
memcpy(to, from, 1);
return;
case kUpb_FieldRep_4Byte:
memcpy(to, from, 4);
return;
case kUpb_FieldRep_8Byte:
memcpy(to, from, 8);
return;
case kUpb_FieldRep_StringView: {
memcpy(to, from, sizeof(upb_StringView));
return;
}
}
UPB_UNREACHABLE();
} }
// Here we define universal getter/setter functions for message fields. // Here we define universal getter/setter functions for message fields.
@ -222,7 +242,7 @@ static UPB_FORCEINLINE void _upb_Message_GetNonExtensionField(
return; return;
} }
UPB_PRIVATE(_upb_MiniTableField_DataCopy) UPB_PRIVATE(_upb_MiniTableField_DataCopy)
(field, val, _upb_MiniTableField_GetConstPtr(msg, field)); (field, val, UPB_PRIVATE(_upb_Message_ConstDataPtr)(msg, field));
} }
UPB_INLINE void _upb_Message_GetExtensionField( UPB_INLINE void _upb_Message_GetExtensionField(
@ -244,7 +264,7 @@ UPB_INLINE void _upb_Message_SetNonExtensionField(
UPB_ASSUME(!upb_MiniTableField_IsExtension(field)); UPB_ASSUME(!upb_MiniTableField_IsExtension(field));
UPB_PRIVATE(_upb_Message_SetPresence)(msg, field); UPB_PRIVATE(_upb_Message_SetPresence)(msg, field);
UPB_PRIVATE(_upb_MiniTableField_DataCopy) UPB_PRIVATE(_upb_MiniTableField_DataCopy)
(field, _upb_MiniTableField_GetPtr(msg, field), val); (field, UPB_PRIVATE(_upb_Message_DataPtr)(msg, field), val);
} }
UPB_INLINE bool _upb_Message_SetExtensionField( UPB_INLINE bool _upb_Message_SetExtensionField(
@ -273,17 +293,14 @@ UPB_INLINE void _upb_Message_ClearExtensionField(
} }
UPB_INLINE void _upb_Message_ClearNonExtensionField( UPB_INLINE void _upb_Message_ClearNonExtensionField(
struct upb_Message* msg, const upb_MiniTableField* field) { struct upb_Message* msg, const upb_MiniTableField* f) {
if (field->presence > 0) { if (UPB_PRIVATE(_upb_MiniTableField_HasHasbit)(f)) {
UPB_PRIVATE(_upb_Message_ClearHasbit)(msg, field); UPB_PRIVATE(_upb_Message_ClearHasbit)(msg, f);
} else if (upb_MiniTableField_IsInOneof(field)) { } else if (upb_MiniTableField_IsInOneof(f)) {
uint32_t* ptr = UPB_PRIVATE(_upb_Message_OneofCasePtr)(msg, field); if (!UPB_PRIVATE(_upb_Message_ClearOneofCase)(msg, f)) return;
if (*ptr != upb_MiniTableField_Number(field)) return;
*ptr = 0;
} }
const char zeros[16] = {0}; void* data = UPB_PRIVATE(_upb_Message_DataPtr)(msg, f);
UPB_PRIVATE(_upb_MiniTableField_DataCopy) UPB_PRIVATE(_upb_MiniTableField_DataClear)(f, data);
(field, _upb_MiniTableField_GetPtr(msg, field), zeros);
} }
UPB_INLINE void _upb_Message_AssertMapIsUntagged( UPB_INLINE void _upb_Message_AssertMapIsUntagged(

@ -130,16 +130,21 @@ UPB_PRIVATE(_upb_MiniTableField_CType)(const struct upb_MiniTableField* f) {
return upb_FieldType_CType(UPB_PRIVATE(_upb_MiniTableField_Type)(f)); return upb_FieldType_CType(UPB_PRIVATE(_upb_MiniTableField_Type)(f));
} }
UPB_INLINE bool UPB_PRIVATE(_upb_MiniTableField_HasHasbit)(
const struct upb_MiniTableField* f) {
return f->presence > 0;
}
UPB_INLINE char UPB_PRIVATE(_upb_MiniTableField_HasbitMask)( UPB_INLINE char UPB_PRIVATE(_upb_MiniTableField_HasbitMask)(
const struct upb_MiniTableField* f) { const struct upb_MiniTableField* f) {
UPB_ASSERT(f->presence > 0); UPB_ASSERT(UPB_PRIVATE(_upb_MiniTableField_HasHasbit)(f));
const size_t index = f->presence; const size_t index = f->presence;
return 1 << (index % 8); return 1 << (index % 8);
} }
UPB_INLINE size_t UPB_PRIVATE(_upb_MiniTableField_HasbitOffset)( UPB_INLINE size_t UPB_PRIVATE(_upb_MiniTableField_HasbitOffset)(
const struct upb_MiniTableField* f) { const struct upb_MiniTableField* f) {
UPB_ASSERT(f->presence > 0); UPB_ASSERT(UPB_PRIVATE(_upb_MiniTableField_HasHasbit)(f));
const size_t index = f->presence; const size_t index = f->presence;
return index / 8; return index / 8;
} }

@ -695,11 +695,11 @@ static const char* _upb_Decoder_DecodeToSubMessage(
return ptr; return ptr;
} }
/* Set presence if necessary. */ // Set presence if necessary.
if (field->presence > 0) { if (UPB_PRIVATE(_upb_MiniTableField_HasHasbit)(field)) {
UPB_PRIVATE(_upb_Message_SetHasbit)(msg, field); UPB_PRIVATE(_upb_Message_SetHasbit)(msg, field);
} else if (field->presence < 0) { } else if (UPB_PRIVATE(_upb_MiniTableField_IsInOneof)(field)) {
/* Oneof case */ // Oneof case
uint32_t* oneof_case = UPB_PRIVATE(_upb_Message_OneofCasePtr)(msg, field); uint32_t* oneof_case = UPB_PRIVATE(_upb_Message_OneofCasePtr)(msg, field);
if (op == kUpb_DecodeOp_SubMessage && if (op == kUpb_DecodeOp_SubMessage &&
*oneof_case != field->UPB_PRIVATE(number)) { *oneof_case != field->UPB_PRIVATE(number)) {
@ -708,7 +708,7 @@ static const char* _upb_Decoder_DecodeToSubMessage(
*oneof_case = field->UPB_PRIVATE(number); *oneof_case = field->UPB_PRIVATE(number);
} }
/* Store into message. */ // Store into message.
switch (op) { switch (op) {
case kUpb_DecodeOp_SubMessage: { case kUpb_DecodeOp_SubMessage: {
upb_TaggedMessagePtr* submsgp = mem; upb_TaggedMessagePtr* submsgp = mem;

@ -493,7 +493,7 @@ static bool encode_shouldencode(upb_encstate* e, const upb_Message* msg,
default: default:
UPB_UNREACHABLE(); UPB_UNREACHABLE();
} }
} else if (f->presence > 0) { } else if (UPB_PRIVATE(_upb_MiniTableField_HasHasbit)(f)) {
// Proto2 presence: hasbit. // Proto2 presence: hasbit.
return UPB_PRIVATE(_upb_Message_GetHasbit)(msg, f); return UPB_PRIVATE(_upb_Message_GetHasbit)(msg, f);
} else { } else {

Loading…
Cancel
Save