upb: refactor mini_table/enum.h

PiperOrigin-RevId: 584154442
pull/14820/head
Eric Salo 1 year ago committed by Copybara-Service
parent 5ae9efc02c
commit 45b292f119
  1. 10
      upb/mini_table/enum.h
  2. 28
      upb/mini_table/internal/enum.h
  3. 4
      upb/mini_table/internal/file.h
  4. 3
      upb/mini_table/internal/message.h
  5. 7
      upb/mini_table/internal/sub.h
  6. 34
      upb/wire/decode.c

@ -8,6 +8,8 @@
#ifndef UPB_MINI_TABLE_ENUM_H_
#define UPB_MINI_TABLE_ENUM_H_
#include <stdint.h>
#include "upb/mini_table/internal/enum.h"
// Must be last
@ -20,13 +22,9 @@ extern "C" {
#endif
// Validates enum value against range defined by enum mini table.
UPB_INLINE bool upb_MiniTableEnum_CheckValue(const struct upb_MiniTableEnum* e,
UPB_INLINE bool upb_MiniTableEnum_CheckValue(const upb_MiniTableEnum* e,
uint32_t val) {
_kUpb_FastEnumCheck_Status status = _upb_MiniTable_CheckEnumValueFast(e, val);
if (UPB_UNLIKELY(status == _kUpb_FastEnumCheck_CannotCheckFast)) {
return _upb_MiniTable_CheckEnumValueSlow(e, val);
}
return status == _kUpb_FastEnumCheck_ValueIsInEnum ? true : false;
return UPB_PRIVATE(_upb_MiniTableEnum_CheckValue)(e, val);
}
#ifdef __cplusplus

@ -19,30 +19,26 @@ struct upb_MiniTableEnum {
uint32_t data[]; // Bitmask + enumerated values follow.
};
typedef enum {
_kUpb_FastEnumCheck_ValueIsInEnum = 0,
_kUpb_FastEnumCheck_ValueIsNotInEnum = 1,
_kUpb_FastEnumCheck_CannotCheckFast = 2,
} _kUpb_FastEnumCheck_Status;
#ifdef __cplusplus
extern "C" {
#endif
UPB_INLINE _kUpb_FastEnumCheck_Status _upb_MiniTable_CheckEnumValueFast(
UPB_INLINE bool UPB_PRIVATE(_upb_MiniTableEnum_CheckValue)(
const struct upb_MiniTableEnum* e, uint32_t val) {
if (UPB_UNLIKELY(val >= 64)) return _kUpb_FastEnumCheck_CannotCheckFast;
uint64_t mask = e->data[0] | ((uint64_t)e->data[1] << 32);
return (mask & (1ULL << val)) ? _kUpb_FastEnumCheck_ValueIsInEnum
: _kUpb_FastEnumCheck_ValueIsNotInEnum;
}
if (UPB_LIKELY(val < 64)) {
const uint64_t mask = e->data[0] | ((uint64_t)e->data[1] << 32);
const uint64_t bit = 1ULL << val;
return (mask & bit) != 0;
}
if (UPB_LIKELY(val < e->mask_limit)) {
const uint32_t mask = e->data[val / 32];
const uint32_t bit = 1ULL << (val % 32);
return (mask & bit) != 0;
}
UPB_INLINE bool _upb_MiniTable_CheckEnumValueSlow(
const struct upb_MiniTableEnum* e, uint32_t val) {
if (val < e->mask_limit) return e->data[val / 32] & (1ULL << (val % 32));
// OPT: binary search long lists?
const uint32_t* start = &e->data[e->mask_limit / 32];
const uint32_t* limit = &e->data[(e->mask_limit / 32) + e->value_count];
const uint32_t* limit = &e->data[e->mask_limit / 32 + e->value_count];
for (const uint32_t* p = start; p < limit; p++) {
if (*p == val) return true;
}

@ -8,10 +8,6 @@
#ifndef UPB_MINI_TABLE_INTERNAL_FILE_H_
#define UPB_MINI_TABLE_INTERNAL_FILE_H_
#include "upb/mini_table/internal/enum.h"
#include "upb/mini_table/internal/extension.h"
#include "upb/mini_table/internal/message.h"
// Must be last.
#include "upb/port/def.inc"

@ -9,7 +9,6 @@
#define UPB_MINI_TABLE_INTERNAL_MESSAGE_H_
#include "upb/message/types.h"
#include "upb/mini_table/internal/field.h"
// Must be last.
#include "upb/port/def.inc"
@ -35,8 +34,6 @@ typedef enum {
kUpb_ExtMode_IsMapEntry = 4,
} upb_ExtMode;
union upb_MiniTableSub;
// upb_MiniTable represents the memory layout of a given upb_MessageDef.
// The members are public so generated code can initialize them,
// but users MUST NOT directly read or write any of its members.

@ -4,15 +4,18 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
#ifndef UPB_MINI_TABLE_INTERNAL_SUB_H_
#define UPB_MINI_TABLE_INTERNAL_SUB_H_
#include "upb/mini_table/internal/enum.h"
#include "upb/mini_table/internal/message.h"
// Must be last.
#include "upb/port/def.inc"
union upb_MiniTableSub {
const struct upb_MiniTable* submsg;
const struct upb_MiniTableEnum* subenum;
};
#include "upb/port/undef.inc"
#endif /* UPB_MINI_TABLE_INTERNAL_SUB_H_ */

@ -33,7 +33,6 @@
#include "upb/mini_table/extension.h"
#include "upb/mini_table/extension_registry.h"
#include "upb/mini_table/field.h"
#include "upb/mini_table/internal/enum.h"
#include "upb/mini_table/internal/field.h"
#include "upb/mini_table/internal/message.h"
#include "upb/mini_table/message.h"
@ -356,34 +355,23 @@ static void _upb_Decoder_AddUnknownVarints(upb_Decoder* d, upb_Message* msg,
}
}
UPB_NOINLINE
static bool _upb_Decoder_CheckEnumSlow(upb_Decoder* d, const char* ptr,
upb_Message* msg,
const upb_MiniTableEnum* e,
const upb_MiniTableField* field,
uint32_t v) {
if (_upb_MiniTable_CheckEnumValueSlow(e, v)) return true;
// Unrecognized enum goes into unknown fields.
// For packed fields the tag could be arbitrarily far in the past, so we
// just re-encode the tag and value here.
uint32_t tag = ((uint32_t)field->number << 3) | kUpb_WireType_Varint;
upb_Message* unknown_msg =
field->mode & kUpb_LabelFlags_IsExtension ? d->unknown_msg : msg;
_upb_Decoder_AddUnknownVarints(d, unknown_msg, tag, v);
return false;
}
UPB_FORCEINLINE
static bool _upb_Decoder_CheckEnum(upb_Decoder* d, const char* ptr,
upb_Message* msg, const upb_MiniTableEnum* e,
const upb_MiniTableField* field,
wireval* val) {
uint32_t v = val->uint32_val;
const uint32_t v = val->uint32_val;
_kUpb_FastEnumCheck_Status status = _upb_MiniTable_CheckEnumValueFast(e, v);
if (UPB_LIKELY(status == _kUpb_FastEnumCheck_ValueIsInEnum)) return true;
return _upb_Decoder_CheckEnumSlow(d, ptr, msg, e, field, v);
if (UPB_LIKELY(upb_MiniTableEnum_CheckValue(e, v))) return true;
// Unrecognized enum goes into unknown fields.
// For packed fields the tag could be arbitrarily far in the past,
// so we just re-encode the tag and value here.
const uint32_t tag = ((uint32_t)field->number << 3) | kUpb_WireType_Varint;
upb_Message* unknown_msg =
field->mode & kUpb_LabelFlags_IsExtension ? d->unknown_msg : msg;
_upb_Decoder_AddUnknownVarints(d, unknown_msg, tag, v);
return false;
}
UPB_NOINLINE

Loading…
Cancel
Save