From 4ba7d2720187aa468bff2a89f55de3ae989a401a Mon Sep 17 00:00:00 2001 From: Eric Salo Date: Mon, 1 Jan 2024 21:29:20 -0800 Subject: [PATCH] upb: implement _upb_Message_ClearOneofCase() PiperOrigin-RevId: 595018281 --- upb/message/BUILD | 1 + upb/message/internal/accessors.h | 117 ++++++++++++++++++------------- upb/mini_table/internal/field.h | 9 ++- upb/wire/decode.c | 10 +-- upb/wire/encode.c | 2 +- 5 files changed, 81 insertions(+), 58 deletions(-) diff --git a/upb/message/BUILD b/upb/message/BUILD index 6988edbc16..d6f4528d8a 100644 --- a/upb/message/BUILD +++ b/upb/message/BUILD @@ -72,6 +72,7 @@ cc_library( "//upb:port", "//upb/base:internal", "//upb/hash", + "//upb/mini_table:internal", ], ) diff --git a/upb/message/internal/accessors.h b/upb/message/internal/accessors.h index 5a84b0259a..94f2c8429b 100644 --- a/upb/message/internal/accessors.h +++ b/upb/message/internal/accessors.h @@ -20,6 +20,7 @@ #include "upb/message/internal/tagged_ptr.h" #include "upb/mini_table/extension.h" #include "upb/mini_table/field.h" +#include "upb/mini_table/internal/field.h" // Must be last. #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)( 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)( struct upb_Message* msg, const upb_MiniTableField* f) { - *UPB_PRIVATE(_upb_Message_OneofCasePtr)(msg, f) = - upb_MiniTableField_Number(f); + uint32_t* ptr = UPB_PRIVATE(_upb_Message_OneofCasePtr)(msg, 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) -UPB_INLINE void* _upb_MiniTableField_GetPtr(struct upb_Message* msg, - const upb_MiniTableField* field) { - return (char*)msg + field->UPB_ONLYBITS(offset); +UPB_INLINE void* UPB_PRIVATE(_upb_Message_DataPtr)( + struct upb_Message* msg, const upb_MiniTableField* f) { + return (char*)msg + f->UPB_ONLYBITS(offset); } -UPB_INLINE const void* _upb_MiniTableField_GetConstPtr( - const struct upb_Message* msg, const upb_MiniTableField* field) { - return (char*)msg + field->UPB_ONLYBITS(offset); +UPB_INLINE const void* UPB_PRIVATE(_upb_Message_ConstDataPtr)( + const struct upb_Message* msg, const upb_MiniTableField* f) { + return (const char*)msg + f->UPB_ONLYBITS(offset); } UPB_INLINE void UPB_PRIVATE(_upb_Message_SetPresence)( - struct upb_Message* msg, const upb_MiniTableField* field) { - if (field->presence > 0) { - UPB_PRIVATE(_upb_Message_SetHasbit)(msg, field); - } else if (upb_MiniTableField_IsInOneof(field)) { - UPB_PRIVATE(_upb_Message_SetOneofCase)(msg, field); + struct upb_Message* msg, const upb_MiniTableField* f) { + if (UPB_PRIVATE(_upb_MiniTableField_HasHasbit)(f)) { + UPB_PRIVATE(_upb_Message_SetHasbit)(msg, f); + } else if (upb_MiniTableField_IsInOneof(f)) { + 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)( - const upb_MiniTableField* field, const void* a, const void* b) { - switch (UPB_PRIVATE(_upb_MiniTableField_GetRep)(field)) { + const upb_MiniTableField* f, const void* a, const void* b) { + switch (UPB_PRIVATE(_upb_MiniTableField_GetRep)(f)) { case kUpb_FieldRep_1Byte: return memcmp(a, b, 1) == 0; case kUpb_FieldRep_4Byte: @@ -134,30 +168,16 @@ UPB_INLINE bool UPB_PRIVATE(_upb_MiniTableField_DataEquals)( UPB_UNREACHABLE(); } -UPB_INLINE bool UPB_PRIVATE(_upb_MiniTableField_DataIsZero)( - const upb_MiniTableField* field, const void* val) { +UPB_INLINE void UPB_PRIVATE(_upb_MiniTableField_DataClear)( + const upb_MiniTableField* f, void* val) { 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)( - const upb_MiniTableField* field, void* to, const void* from) { - switch (UPB_PRIVATE(_upb_MiniTableField_GetRep)(field)) { - 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_DataIsZero)( + const upb_MiniTableField* f, const void* val) { + const char zero[16] = {0}; + return UPB_PRIVATE(_upb_MiniTableField_DataEquals)(f, val, zero); } // Here we define universal getter/setter functions for message fields. @@ -222,7 +242,7 @@ static UPB_FORCEINLINE void _upb_Message_GetNonExtensionField( return; } 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( @@ -244,7 +264,7 @@ UPB_INLINE void _upb_Message_SetNonExtensionField( UPB_ASSUME(!upb_MiniTableField_IsExtension(field)); UPB_PRIVATE(_upb_Message_SetPresence)(msg, field); 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( @@ -273,17 +293,14 @@ UPB_INLINE void _upb_Message_ClearExtensionField( } UPB_INLINE void _upb_Message_ClearNonExtensionField( - struct upb_Message* msg, const upb_MiniTableField* field) { - if (field->presence > 0) { - UPB_PRIVATE(_upb_Message_ClearHasbit)(msg, field); - } else if (upb_MiniTableField_IsInOneof(field)) { - uint32_t* ptr = UPB_PRIVATE(_upb_Message_OneofCasePtr)(msg, field); - if (*ptr != upb_MiniTableField_Number(field)) return; - *ptr = 0; + struct upb_Message* msg, const upb_MiniTableField* f) { + if (UPB_PRIVATE(_upb_MiniTableField_HasHasbit)(f)) { + UPB_PRIVATE(_upb_Message_ClearHasbit)(msg, f); + } else if (upb_MiniTableField_IsInOneof(f)) { + if (!UPB_PRIVATE(_upb_Message_ClearOneofCase)(msg, f)) return; } - const char zeros[16] = {0}; - UPB_PRIVATE(_upb_MiniTableField_DataCopy) - (field, _upb_MiniTableField_GetPtr(msg, field), zeros); + void* data = UPB_PRIVATE(_upb_Message_DataPtr)(msg, f); + UPB_PRIVATE(_upb_MiniTableField_DataClear)(f, data); } UPB_INLINE void _upb_Message_AssertMapIsUntagged( diff --git a/upb/mini_table/internal/field.h b/upb/mini_table/internal/field.h index 37568e017b..166463a886 100644 --- a/upb/mini_table/internal/field.h +++ b/upb/mini_table/internal/field.h @@ -130,16 +130,21 @@ UPB_PRIVATE(_upb_MiniTableField_CType)(const struct upb_MiniTableField* 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)( const struct upb_MiniTableField* f) { - UPB_ASSERT(f->presence > 0); + UPB_ASSERT(UPB_PRIVATE(_upb_MiniTableField_HasHasbit)(f)); const size_t index = f->presence; return 1 << (index % 8); } UPB_INLINE size_t UPB_PRIVATE(_upb_MiniTableField_HasbitOffset)( const struct upb_MiniTableField* f) { - UPB_ASSERT(f->presence > 0); + UPB_ASSERT(UPB_PRIVATE(_upb_MiniTableField_HasHasbit)(f)); const size_t index = f->presence; return index / 8; } diff --git a/upb/wire/decode.c b/upb/wire/decode.c index 6d52b3702e..c8270397ab 100644 --- a/upb/wire/decode.c +++ b/upb/wire/decode.c @@ -695,11 +695,11 @@ static const char* _upb_Decoder_DecodeToSubMessage( return ptr; } - /* Set presence if necessary. */ - if (field->presence > 0) { + // Set presence if necessary. + if (UPB_PRIVATE(_upb_MiniTableField_HasHasbit)(field)) { UPB_PRIVATE(_upb_Message_SetHasbit)(msg, field); - } else if (field->presence < 0) { - /* Oneof case */ + } else if (UPB_PRIVATE(_upb_MiniTableField_IsInOneof)(field)) { + // Oneof case uint32_t* oneof_case = UPB_PRIVATE(_upb_Message_OneofCasePtr)(msg, field); if (op == kUpb_DecodeOp_SubMessage && *oneof_case != field->UPB_PRIVATE(number)) { @@ -708,7 +708,7 @@ static const char* _upb_Decoder_DecodeToSubMessage( *oneof_case = field->UPB_PRIVATE(number); } - /* Store into message. */ + // Store into message. switch (op) { case kUpb_DecodeOp_SubMessage: { upb_TaggedMessagePtr* submsgp = mem; diff --git a/upb/wire/encode.c b/upb/wire/encode.c index aeec7edec3..12a6d32b6f 100644 --- a/upb/wire/encode.c +++ b/upb/wire/encode.c @@ -493,7 +493,7 @@ static bool encode_shouldencode(upb_encstate* e, const upb_Message* msg, default: UPB_UNREACHABLE(); } - } else if (f->presence > 0) { + } else if (UPB_PRIVATE(_upb_MiniTableField_HasHasbit)(f)) { // Proto2 presence: hasbit. return UPB_PRIVATE(_upb_Message_GetHasbit)(msg, f); } else {