upb: implement upb_Message

PiperOrigin-RevId: 597662892
pull/15307/head
Eric Salo 11 months ago committed by Copybara-Service
parent 81ce69985a
commit 5c5f092606
  1. 1
      upb/message/BUILD
  2. 4
      upb/message/accessors.h
  3. 2
      upb/message/copy.c
  4. 18
      upb/message/internal/accessors.h
  5. 4
      upb/message/internal/extension.c
  6. 6
      upb/message/internal/map_sorter.h
  7. 9
      upb/message/internal/message.c
  8. 61
      upb/message/internal/message.h
  9. 14
      upb/message/message.c
  10. 2
      upb/message/test.cc
  11. 42
      upb/mini_descriptor/decode.c
  12. 3
      upb/mini_table/BUILD
  13. 24
      upb/mini_table/internal/map_entry.h
  14. 4
      upb/mini_table/internal/message.c
  15. 13
      upb/mini_table/internal/message.h
  16. 22
      upb/mini_table/internal/types.h
  17. 2
      upb/text/BUILD
  18. 14
      upb/text/encode.c
  19. 49
      upb/wire/decode.c
  20. 22
      upb/wire/encode.c
  21. 10
      upb/wire/internal/decode_fast.c

@ -60,7 +60,6 @@ cc_library(
"internal/array.h",
"internal/extension.h",
"internal/map.h",
"internal/map_entry.h",
"internal/map_sorter.h",
"internal/message.h",
"internal/tagged_ptr.h",

@ -42,9 +42,7 @@ extern "C" {
UPB_API_INLINE void upb_Message_Clear(upb_Message* msg,
const upb_MiniTable* m) {
// Note: Can't use UPB_PTR_AT() here because we are doing pointer subtraction.
char* mem = (char*)msg - sizeof(upb_Message_Internal);
memset(mem, 0, upb_msg_sizeof(m));
UPB_PRIVATE(_upb_Message_Clear)(msg, m);
}
UPB_API_INLINE void upb_Message_ClearBaseField(upb_Message* msg,

@ -191,7 +191,7 @@ upb_Message* _upb_Message_Copy(upb_Message* dst, const upb_Message* src,
upb_Arena* arena) {
upb_StringView empty_string = upb_StringView_FromDataAndSize(NULL, 0);
// Only copy message area skipping upb_Message_Internal.
memcpy(dst, src, mini_table->UPB_PRIVATE(size));
memcpy(dst + 1, src + 1, mini_table->UPB_PRIVATE(size) - sizeof(upb_Message));
for (size_t i = 0; i < mini_table->UPB_PRIVATE(field_count); ++i) {
const upb_MiniTableField* field = &mini_table->UPB_PRIVATE(fields)[i];
if (upb_MiniTableField_IsScalar(field)) {

@ -12,6 +12,7 @@
#include <stdint.h>
#include <string.h>
#include "upb/base/internal/endian.h"
#include "upb/base/string_view.h"
#include "upb/mem/arena.h"
#include "upb/message/internal/extension.h"
@ -21,6 +22,7 @@
#include "upb/mini_table/extension.h"
#include "upb/mini_table/field.h"
#include "upb/mini_table/internal/field.h"
#include "upb/mini_table/message.h"
// Must be last.
#include "upb/port/def.inc"
@ -111,6 +113,15 @@ UPB_INLINE bool UPB_PRIVATE(_upb_Message_ClearOneofCase)(
// LINT.ThenChange(GoogleInternalName2)
// Returns false if the message is missing any of its required fields.
UPB_INLINE bool UPB_PRIVATE(_upb_Message_IsInitializedShallow)(
const struct upb_Message* msg, const upb_MiniTable* m) {
uint64_t bits;
memcpy(&bits, msg + 1, sizeof(bits));
bits = upb_BigEndian64(bits);
return (UPB_PRIVATE(_upb_MiniTable_RequiredMask)(m) & ~bits) == 0;
}
UPB_INLINE void* UPB_PRIVATE(_upb_Message_MutableDataPtr)(
struct upb_Message* msg, const upb_MiniTableField* f) {
return (char*)msg + f->UPB_ONLYBITS(offset);
@ -278,6 +289,11 @@ UPB_INLINE bool _upb_Message_SetExtensionField(
return true;
}
UPB_INLINE void UPB_PRIVATE(_upb_Message_Clear)(struct upb_Message* msg,
const upb_MiniTable* m) {
memset(msg, 0, m->UPB_PRIVATE(size));
}
UPB_INLINE void UPB_PRIVATE(_upb_Message_ClearBaseField)(
struct upb_Message* msg, const upb_MiniTableField* f) {
if (UPB_PRIVATE(_upb_MiniTableField_HasHasbit)(f)) {
@ -294,7 +310,7 @@ UPB_INLINE void UPB_PRIVATE(_upb_Message_ClearBaseField)(
UPB_INLINE void UPB_PRIVATE(_upb_Message_ClearExtension)(
struct upb_Message* msg, const upb_MiniTableExtension* e) {
upb_Message_InternalData* in = upb_Message_GetInternalData(msg);
upb_Message_Internal* in = msg->internal;
if (!in) return;
const struct upb_Extension* base =
UPB_PTR_AT(in, in->ext_begin, struct upb_Extension);

@ -36,7 +36,7 @@ const struct upb_Extension* _upb_Message_Getext(
const struct upb_Extension* UPB_PRIVATE(_upb_Message_Getexts)(
const struct upb_Message* msg, size_t* count) {
upb_Message_InternalData* in = upb_Message_GetInternalData(msg);
upb_Message_Internal* in = msg->internal;
if (in) {
*count = (in->size - in->ext_begin) / sizeof(struct upb_Extension);
return UPB_PTR_AT(in, in->ext_begin, void);
@ -53,7 +53,7 @@ struct upb_Extension* _upb_Message_GetOrCreateExtension(
if (ext) return ext;
if (!UPB_PRIVATE(_upb_Message_Realloc)(msg, sizeof(struct upb_Extension), a))
return NULL;
upb_Message_InternalData* in = upb_Message_GetInternalData(msg);
upb_Message_Internal* in = msg->internal;
in->ext_begin -= sizeof(struct upb_Extension);
ext = UPB_PTR_AT(in, in->ext_begin, void);
memset(ext, 0, sizeof(struct upb_Extension));

@ -17,7 +17,7 @@
#include "upb/mem/alloc.h"
#include "upb/message/internal/extension.h"
#include "upb/message/internal/map.h"
#include "upb/message/internal/map_entry.h"
#include "upb/mini_table/internal/map_entry.h"
// Must be last.
#include "upb/port/def.inc"
@ -58,9 +58,9 @@ UPB_INLINE bool _upb_sortedmap_next(_upb_mapsorter* s,
if (sorted->pos == sorted->end) return false;
const upb_tabent* tabent = (const upb_tabent*)s->entries[sorted->pos++];
upb_StringView key = upb_tabstrview(tabent->key);
_upb_map_fromkey(key, &ent->data.k, map->key_size);
_upb_map_fromkey(key, &ent->k, map->key_size);
upb_value val = {tabent->val.val};
_upb_map_fromvalue(val, &ent->data.v, map->val_size);
_upb_map_fromvalue(val, &ent->v, map->val_size);
return true;
}

@ -22,10 +22,9 @@ const double kUpb_NaN = NAN;
bool UPB_PRIVATE(_upb_Message_Realloc)(struct upb_Message* msg, size_t need,
upb_Arena* a) {
const size_t overhead = sizeof(upb_Message_InternalData);
const size_t overhead = sizeof(upb_Message_Internal);
upb_Message_Internal* owner = upb_Message_Getinternal(msg);
upb_Message_InternalData* in = owner->internal;
upb_Message_Internal* in = msg->internal;
if (!in) {
// No internal data, allocate from scratch.
size_t size = UPB_MAX(128, upb_Log2CeilingSize(need + overhead));
@ -35,7 +34,7 @@ bool UPB_PRIVATE(_upb_Message_Realloc)(struct upb_Message* msg, size_t need,
in->size = size;
in->unknown_end = overhead;
in->ext_begin = size;
owner->internal = in;
msg->internal = in;
} else if (in->ext_begin - in->unknown_end < need) {
// Internal data is too small, reallocate.
size_t new_size = upb_Log2CeilingSize(in->size + need);
@ -51,7 +50,7 @@ bool UPB_PRIVATE(_upb_Message_Realloc)(struct upb_Message* msg, size_t need,
}
in->ext_begin = new_ext_begin;
in->size = new_size;
owner->internal = in;
msg->internal = in;
}
UPB_ASSERT(in->ext_begin - in->unknown_end >= need);

@ -20,6 +20,7 @@
#include "upb/mem/arena.h"
#include "upb/message/internal/extension.h"
#include "upb/mini_table/internal/types.h"
#include "upb/mini_table/message.h"
// Must be last.
@ -33,14 +34,12 @@ extern const float kUpb_FltInfinity;
extern const double kUpb_Infinity;
extern const double kUpb_NaN;
/* Internal members of a upb_Message that track unknown fields and/or
* extensions. We can change this without breaking binary compatibility. We put
* these before the user's data. The user's upb_Message* points after the
* upb_Message_Internal. */
// Internal members of a upb_Message that track unknown fields and/or
// extensions. We can change this without breaking binary compatibility.
typedef struct {
/* Total size of this structure, including the data that follows.
* Must be aligned to 8, which is alignof(upb_Extension) */
typedef struct upb_Message_Internal {
// Total size of this structure, including the data that follows.
// Must be aligned to 8, which is alignof(upb_Extension)
uint32_t size;
/* Offsets relative to the beginning of this structure.
@ -50,8 +49,7 @@ typedef struct {
* When the two meet, we're out of data and have to realloc.
*
* If we imagine that the final member of this struct is:
* char data[size - overhead]; // overhead =
* sizeof(upb_Message_InternalData)
* char data[size - overhead]; // overhead = sizeof(upb_Message_Internal)
*
* Then we have:
* unknown data: data[0 .. (unknown_end - overhead)]
@ -59,50 +57,19 @@ typedef struct {
uint32_t unknown_end;
uint32_t ext_begin;
/* Data follows, as if there were an array:
* char data[size - sizeof(upb_Message_InternalData)]; */
} upb_Message_InternalData;
typedef struct {
union {
upb_Message_InternalData* internal;
// Force 8-byte alignment, since the data members may contain members that
// require 8-byte alignment.
double d;
};
* char data[size - sizeof(upb_Message_Internal)]; */
} upb_Message_Internal;
struct upb_Message {
int unused; // Placeholder cuz Windows won't compile an empty struct.
};
UPB_INLINE size_t upb_msg_sizeof(const upb_MiniTable* m) {
return m->UPB_PRIVATE(size) + sizeof(upb_Message_Internal);
}
// Inline version upb_Message_New(), for internal use.
UPB_INLINE struct upb_Message* _upb_Message_New(const upb_MiniTable* mini_table,
upb_Arena* arena) {
size_t size = upb_msg_sizeof(mini_table);
void* mem = upb_Arena_Malloc(arena, size + sizeof(upb_Message_Internal));
if (UPB_UNLIKELY(!mem)) return NULL;
struct upb_Message* msg =
UPB_PTR_AT(mem, sizeof(upb_Message_Internal), struct upb_Message);
memset(mem, 0, size);
UPB_INLINE struct upb_Message* _upb_Message_New(const upb_MiniTable* m,
upb_Arena* a) {
const int size = m->UPB_PRIVATE(size);
struct upb_Message* msg = (struct upb_Message*)upb_Arena_Malloc(a, size);
if (UPB_UNLIKELY(!msg)) return NULL;
memset(msg, 0, size);
return msg;
}
UPB_INLINE upb_Message_Internal* upb_Message_Getinternal(
const struct upb_Message* msg) {
ptrdiff_t size = sizeof(upb_Message_Internal);
return (upb_Message_Internal*)((char*)msg - size);
}
UPB_INLINE upb_Message_InternalData* upb_Message_GetInternalData(
const struct upb_Message* msg) {
return upb_Message_Getinternal(msg)->internal;
}
// Discards the unknown fields for this message only.
void _upb_Message_DiscardUnknown_shallow(struct upb_Message* msg);

@ -18,7 +18,7 @@
// Must be last.
#include "upb/port/def.inc"
static const size_t message_overhead = sizeof(upb_Message_InternalData);
static const size_t message_overhead = sizeof(upb_Message_Internal);
upb_Message* upb_Message_New(const upb_MiniTable* m, upb_Arena* a) {
return _upb_Message_New(m, a);
@ -27,24 +27,21 @@ upb_Message* upb_Message_New(const upb_MiniTable* m, upb_Arena* a) {
bool UPB_PRIVATE(_upb_Message_AddUnknown)(upb_Message* msg, const char* data,
size_t len, upb_Arena* arena) {
if (!UPB_PRIVATE(_upb_Message_Realloc)(msg, len, arena)) return false;
upb_Message_Internal* owner = upb_Message_Getinternal(msg);
upb_Message_InternalData* in = owner->internal;
upb_Message_Internal* in = msg->internal;
memcpy(UPB_PTR_AT(in, in->unknown_end, char), data, len);
in->unknown_end += len;
return true;
}
void _upb_Message_DiscardUnknown_shallow(upb_Message* msg) {
upb_Message_Internal* owner = upb_Message_Getinternal(msg);
upb_Message_InternalData* in = owner->internal;
upb_Message_Internal* in = msg->internal;
if (in) {
in->unknown_end = message_overhead;
}
}
const char* upb_Message_GetUnknown(const upb_Message* msg, size_t* len) {
upb_Message_Internal* owner = upb_Message_Getinternal(msg);
upb_Message_InternalData* in = owner->internal;
upb_Message_Internal* in = msg->internal;
if (in) {
*len = in->unknown_end - message_overhead;
return (char*)(in + 1);
@ -55,8 +52,7 @@ const char* upb_Message_GetUnknown(const upb_Message* msg, size_t* len) {
}
void upb_Message_DeleteUnknown(upb_Message* msg, const char* data, size_t len) {
upb_Message_Internal* owner = upb_Message_Getinternal(msg);
upb_Message_InternalData* in = owner->internal;
upb_Message_Internal* in = msg->internal;
const char* internal_unknown_end = UPB_PTR_AT(in, in->unknown_end, char);
#ifndef NDEBUG

@ -669,7 +669,7 @@ TEST(MessageTest, MapField) {
// TEST(FuzzTest, TooManyRequiredFields) {
// DecodeEncodeArbitrarySchemaAndPayload(
// {{"$ N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N "
// "N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N"},
// "N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N"},
// {},
// "",
// {}},

@ -8,6 +8,7 @@
#include "upb/mini_descriptor/decode.h"
#include <inttypes.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
@ -23,13 +24,21 @@
#include "upb/mini_table/extension.h"
#include "upb/mini_table/field.h"
#include "upb/mini_table/internal/field.h"
#include "upb/mini_table/internal/map_entry.h"
#include "upb/mini_table/internal/message.h"
#include "upb/mini_table/internal/types.h"
#include "upb/mini_table/message.h"
#include "upb/mini_table/sub.h"
// Must be last.
#include "upb/port/def.inc"
// We reserve unused hasbits to make room for upb_Message fields.
#define kUpb_Reserved_Hasbytes sizeof(struct upb_Message)
// 64 is the first hasbit that we currently use.
#define kUpb_Reserved_Hasbits (kUpb_Reserved_Hasbytes * 8)
// Note: we sort by this number when calculating layout order.
typedef enum {
kUpb_LayoutItemType_OneofCase, // Oneof case.
@ -268,8 +277,8 @@ static void upb_MtDecoder_PushOneof(upb_MtDecoder* d, upb_LayoutItem item) {
upb_MtDecoder_PushItem(d, item);
}
size_t upb_MtDecoder_SizeOfRep(upb_FieldRep rep,
upb_MiniTablePlatform platform) {
static size_t upb_MtDecoder_SizeOfRep(upb_FieldRep rep,
upb_MiniTablePlatform platform) {
static const uint8_t kRepToSize32[] = {
[kUpb_FieldRep_1Byte] = 1,
[kUpb_FieldRep_4Byte] = 4,
@ -288,8 +297,8 @@ size_t upb_MtDecoder_SizeOfRep(upb_FieldRep rep,
: kRepToSize64[rep];
}
size_t upb_MtDecoder_AlignOfRep(upb_FieldRep rep,
upb_MiniTablePlatform platform) {
static size_t upb_MtDecoder_AlignOfRep(upb_FieldRep rep,
upb_MiniTablePlatform platform) {
static const uint8_t kRepToAlign32[] = {
[kUpb_FieldRep_1Byte] = 1,
[kUpb_FieldRep_4Byte] = 4,
@ -491,7 +500,7 @@ static void upb_MtDecoder_ParseMessage(upb_MtDecoder* d, const char* data,
upb_MtDecoder_AllocateSubs(d, sub_counts);
}
int upb_MtDecoder_CompareFields(const void* _a, const void* _b) {
static int upb_MtDecoder_CompareFields(const void* _a, const void* _b) {
const upb_LayoutItem* a = _a;
const upb_LayoutItem* b = _b;
// Currently we just sort by:
@ -539,7 +548,7 @@ static size_t upb_MiniTable_DivideRoundUp(size_t n, size_t d) {
static void upb_MtDecoder_AssignHasbits(upb_MtDecoder* d) {
upb_MiniTable* ret = d->table;
int n = ret->UPB_PRIVATE(field_count);
int last_hasbit = 0; // 0 cannot be used.
size_t last_hasbit = kUpb_Reserved_Hasbits - 1;
// First assign required fields, which must have the lowest hasbits.
for (int i = 0; i < n; i++) {
@ -551,11 +560,11 @@ static void upb_MtDecoder_AssignHasbits(upb_MtDecoder* d) {
field->presence = 0;
}
}
if (last_hasbit > 63) {
if (last_hasbit > kUpb_Reserved_Hasbits + 63) {
upb_MdDecoder_ErrorJmp(&d->base, "Too many required fields");
}
ret->UPB_PRIVATE(required_count) = last_hasbit;
ret->UPB_PRIVATE(required_count) = last_hasbit - (kUpb_Reserved_Hasbits - 1);
// Next assign non-required hasbit fields.
for (int i = 0; i < n; i++) {
@ -570,7 +579,7 @@ static void upb_MtDecoder_AssignHasbits(upb_MtDecoder* d) {
last_hasbit ? upb_MiniTable_DivideRoundUp(last_hasbit + 1, 8) : 0;
}
size_t upb_MtDecoder_Place(upb_MtDecoder* d, upb_FieldRep rep) {
static size_t upb_MtDecoder_Place(upb_MtDecoder* d, upb_FieldRep rep) {
size_t size = upb_MtDecoder_SizeOfRep(rep, d->platform);
size_t align = upb_MtDecoder_AlignOfRep(rep, d->platform);
size_t ret = UPB_ALIGN_UP(d->table->UPB_PRIVATE(size), align);
@ -686,14 +695,9 @@ static void upb_MtDecoder_ParseMap(upb_MtDecoder* d, const char* data,
upb_MtDecoder_ValidateEntryField(d, &d->table->UPB_PRIVATE(fields)[0], 1);
upb_MtDecoder_ValidateEntryField(d, &d->table->UPB_PRIVATE(fields)[1], 2);
// Map entries have a pre-determined layout, regardless of types.
// NOTE: sync with mini_table/message_internal.h.
const size_t kv_size = d->platform == kUpb_MiniTablePlatform_32Bit ? 8 : 16;
const size_t hasbit_size = 8;
d->fields[0].UPB_PRIVATE(offset) = hasbit_size;
d->fields[1].UPB_PRIVATE(offset) = hasbit_size + kv_size;
d->table->UPB_PRIVATE(size) =
UPB_ALIGN_UP(hasbit_size + kv_size + kv_size, 8);
d->fields[0].UPB_PRIVATE(offset) = offsetof(upb_MapEntry, k);
d->fields[1].UPB_PRIVATE(offset) = offsetof(upb_MapEntry, v);
d->table->UPB_PRIVATE(size) = sizeof(upb_MapEntry);
// Map entries have a special bit set to signal it's a map entry, used in
// upb_MiniTable_SetSubMessage() below.
@ -708,7 +712,7 @@ static void upb_MtDecoder_ParseMessageSet(upb_MtDecoder* d, const char* data,
}
upb_MiniTable* ret = d->table;
ret->UPB_PRIVATE(size) = 0;
ret->UPB_PRIVATE(size) = kUpb_Reserved_Hasbytes;
ret->UPB_PRIVATE(field_count) = 0;
ret->UPB_PRIVATE(ext) = kUpb_ExtMode_IsMessageSet;
ret->UPB_PRIVATE(dense_below) = 0;
@ -721,7 +725,7 @@ static upb_MiniTable* upb_MtDecoder_DoBuildMiniTableWithBuf(
size_t* buf_size) {
upb_MdDecoder_CheckOutOfMemory(&decoder->base, decoder->table);
decoder->table->UPB_PRIVATE(size) = 0;
decoder->table->UPB_PRIVATE(size) = kUpb_Reserved_Hasbytes;
decoder->table->UPB_PRIVATE(field_count) = 0;
decoder->table->UPB_PRIVATE(ext) = kUpb_ExtMode_NonExtendable;
decoder->table->UPB_PRIVATE(dense_below) = 0;

@ -46,9 +46,11 @@ cc_library(
"internal/extension.h",
"internal/field.h",
"internal/file.h",
"internal/map_entry.h",
"internal/message.h",
"internal/size_log2.h",
"internal/sub.h",
"internal/types.h",
],
copts = UPB_DEFAULT_COPTS,
visibility = ["//visibility:public"],
@ -56,6 +58,7 @@ cc_library(
"//upb:base",
"//upb:mem",
"//upb:port",
"//upb/hash",
],
)

@ -5,41 +5,37 @@
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
#ifndef UPB_MESSAGE_INTERNAL_MAP_ENTRY_H_
#define UPB_MESSAGE_INTERNAL_MAP_ENTRY_H_
#ifndef UPB_MINI_TABLE_INTERNAL_MAP_ENTRY_H_
#define UPB_MINI_TABLE_INTERNAL_MAP_ENTRY_H_
#include <stdint.h>
#include "upb/base/string_view.h"
#include "upb/hash/common.h"
#include "upb/message/internal/message.h"
#include "upb/mini_table/internal/types.h"
// Map entries aren't actually stored for map fields, they are only used during
// parsing. For parsing, it helps a lot if all map entry messages have the same
// layout. The layout code in mini_table/decode.c will ensure that all map
// entries have this layout.
// parsing. (It helps a lot if all map entry messages have the same layout.)
// The mini_table layout code will ensure that all map entries have this layout.
//
// Note that users can and do create map entries directly, which will also use
// this layout.
//
// NOTE: sync with wire/decode.c.
typedef struct {
struct upb_Message message;
// We only need 2 hasbits max, but due to alignment we'll use 8 bytes here,
// and the uint64_t helps make this clear.
uint64_t hasbits;
union {
upb_StringView str; // For str/bytes.
upb_value val; // For all other types.
double d[2]; // Padding for 32-bit builds.
} k;
union {
upb_StringView str; // For str/bytes.
upb_value val; // For all other types.
double d[2]; // Padding for 32-bit builds.
} v;
} upb_MapEntryData;
typedef struct {
upb_Message_Internal internal;
upb_MapEntryData data;
} upb_MapEntry;
#endif // UPB_MESSAGE_INTERNAL_MAP_ENTRY_H_
#endif // UPB_MINI_TABLE_INTERNAL_MAP_ENTRY_H_

@ -9,6 +9,8 @@
#include <stddef.h>
#include "upb/mini_table/internal/types.h"
// Must be last.
#include "upb/port/def.inc"
@ -16,7 +18,7 @@
const struct upb_MiniTable UPB_PRIVATE(_kUpb_MiniTable_Empty) = {
.UPB_PRIVATE(subs) = NULL,
.UPB_PRIVATE(fields) = NULL,
.UPB_PRIVATE(size) = 0,
.UPB_PRIVATE(size) = sizeof(struct upb_Message),
.UPB_PRIVATE(field_count) = 0,
.UPB_PRIVATE(ext) = kUpb_ExtMode_NonExtendable,
.UPB_PRIVATE(dense_below) = 0,

@ -12,12 +12,12 @@
#include "upb/mini_table/internal/field.h"
#include "upb/mini_table/internal/sub.h"
#include "upb/mini_table/internal/types.h"
// Must be last.
#include "upb/port/def.inc"
struct upb_Decoder;
struct upb_Message;
typedef const char* _upb_FieldParser(struct upb_Decoder* d, const char* ptr,
struct upb_Message* msg, intptr_t table,
uint64_t hasbits, uint64_t data);
@ -138,17 +138,16 @@ UPB_INLINE bool UPB_PRIVATE(_upb_MiniTable_MessageFieldIsLinked)(
return UPB_PRIVATE(_upb_MiniTable_GetSubMessageTable)(m, f) != NULL;
}
// Computes a bitmask in which the |m->required_count| lowest bits are set,
// except that we skip the lowest bit (because upb never uses hasbit 0).
// Computes a bitmask in which the |m->required_count| lowest bits are set.
//
// Sample output:
// RequiredMask(1) => 0b10 (0x2)
// RequiredMask(5) => 0b111110 (0x3e)
// RequiredMask(1) => 0b1 (0x1)
// RequiredMask(5) => 0b11111 (0x1f)
UPB_INLINE uint64_t
UPB_PRIVATE(_upb_MiniTable_RequiredMask)(const struct upb_MiniTable* m) {
int n = m->UPB_PRIVATE(required_count);
UPB_ASSERT(0 < n && n <= 63);
return ((1ULL << n) - 1) << 1;
UPB_ASSERT(0 < n && n <= 64);
return (1ULL << n) - 1;
}
#ifdef __cplusplus

@ -0,0 +1,22 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2023 Google LLC. All rights reserved.
//
// 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_TYPES_H_
#define UPB_MINI_TABLE_INTERNAL_TYPES_H_
// This definition exists here (instead of in upb/message/) as an optimization
// so that minitable code can cleanly know the size of a upb_Message - which is
// also the minimum size of a minitable.
struct upb_Message {
union {
struct upb_Message_Internal* internal;
double d; // Forces same size for 32-bit/64-bit builds
};
};
#endif /* UPB_MINI_TABLE_INTERNAL_TYPES_H_ */

@ -18,6 +18,7 @@ cc_library(
copts = UPB_DEFAULT_COPTS,
visibility = ["//visibility:public"],
deps = [
"//upb:base",
"//upb:eps_copy_input_stream",
"//upb:message",
"//upb:port",
@ -26,6 +27,7 @@ cc_library(
"//upb:wire_reader",
"//upb/lex",
"//upb/message:internal",
"//upb/mini_table:internal",
],
)

@ -11,12 +11,20 @@
#include <float.h>
#include <inttypes.h>
#include <stdarg.h>
#include <stdint.h>
#include <string.h>
#include "upb/base/descriptor_constants.h"
#include "upb/base/string_view.h"
#include "upb/lex/round_trip.h"
#include "upb/message/array.h"
#include "upb/message/internal/map_sorter.h"
#include "upb/message/map.h"
#include "upb/message/message.h"
#include "upb/message/value.h"
#include "upb/mini_table/internal/map_entry.h"
#include "upb/port/vsnprintf_compat.h"
#include "upb/reflection/def.h"
#include "upb/reflection/message.h"
#include "upb/wire/eps_copy_input_stream.h"
#include "upb/wire/reader.h"
@ -277,8 +285,8 @@ static void txtenc_map(txtenc* e, const upb_Map* map, const upb_FieldDef* f) {
_upb_mapsorter_pushmap(&e->sorter, upb_FieldDef_Type(key_f), map, &sorted);
while (_upb_sortedmap_next(&e->sorter, map, &sorted, &ent)) {
upb_MessageValue key, val;
memcpy(&key, &ent.data.k, sizeof(key));
memcpy(&val, &ent.data.v, sizeof(val));
memcpy(&key, &ent.k, sizeof(key));
memcpy(&val, &ent.v, sizeof(val));
txtenc_mapentry(e, key, val, f);
}
_upb_mapsorter_popmap(&e->sorter, &sorted);
@ -369,7 +377,7 @@ static const char* txtenc_unknown(txtenc* e, const char* ptr,
e->overflow = start_overflow;
const char* str = ptr;
ptr = upb_EpsCopyInputStream_ReadString(stream, &str, size, NULL);
assert(ptr);
UPB_ASSERT(ptr);
txtenc_string(e, (upb_StringView){.data = str, .size = size}, true);
}
break;

@ -23,7 +23,6 @@
#include "upb/message/internal/array.h"
#include "upb/message/internal/extension.h"
#include "upb/message/internal/map.h"
#include "upb/message/internal/map_entry.h"
#include "upb/message/internal/message.h"
#include "upb/message/internal/tagged_ptr.h"
#include "upb/message/map.h"
@ -34,6 +33,7 @@
#include "upb/mini_table/extension_registry.h"
#include "upb/mini_table/field.h"
#include "upb/mini_table/internal/field.h"
#include "upb/mini_table/internal/map_entry.h"
#include "upb/mini_table/internal/message.h"
#include "upb/mini_table/internal/size_log2.h"
#include "upb/mini_table/message.h"
@ -615,8 +615,8 @@ static upb_Map* _upb_Decoder_CreateMap(upb_Decoder* d,
const upb_MiniTableField* val_field = &entry->UPB_PRIVATE(fields)[1];
char key_size = kSizeInMap[key_field->UPB_PRIVATE(descriptortype)];
char val_size = kSizeInMap[val_field->UPB_PRIVATE(descriptortype)];
UPB_ASSERT(key_field->UPB_PRIVATE(offset) == offsetof(upb_MapEntryData, k));
UPB_ASSERT(val_field->UPB_PRIVATE(offset) == offsetof(upb_MapEntryData, v));
UPB_ASSERT(key_field->UPB_PRIVATE(offset) == offsetof(upb_MapEntry, k));
UPB_ASSERT(val_field->UPB_PRIVATE(offset) == offsetof(upb_MapEntry, v));
upb_Map* ret = _upb_Map_New(&d->arena, key_size, val_size);
if (!ret) _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_OutOfMemory);
return ret;
@ -654,21 +654,21 @@ static const char* _upb_Decoder_DecodeToMap(upb_Decoder* d, const char* ptr,
upb_TaggedMessagePtr msg;
_upb_Decoder_NewSubMessage(d, entry->UPB_PRIVATE(subs),
&entry->UPB_PRIVATE(fields)[1], &msg);
ent.data.v.val = upb_value_uintptr(msg);
ent.v.val = upb_value_uintptr(msg);
}
ptr = _upb_Decoder_DecodeSubMessage(d, ptr, (upb_Message*)&ent.data, subs,
field, val->size);
ptr = _upb_Decoder_DecodeSubMessage(d, ptr, &ent.message, subs, field,
val->size);
// check if ent had any unknown fields
size_t size;
upb_Message_GetUnknown((upb_Message*)&ent.data, &size);
upb_Message_GetUnknown(&ent.message, &size);
if (size != 0) {
char* buf;
size_t size;
uint32_t tag =
((uint32_t)field->UPB_PRIVATE(number) << 3) | kUpb_WireType_Delimited;
upb_EncodeStatus status =
upb_Encode((upb_Message*)&ent.data, entry, 0, &d->arena, &buf, &size);
upb_Encode(&ent.message, entry, 0, &d->arena, &buf, &size);
if (status != kUpb_EncodeStatus_Ok) {
_upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_OutOfMemory);
}
@ -677,8 +677,7 @@ static const char* _upb_Decoder_DecodeToMap(upb_Decoder* d, const char* ptr,
_upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_OutOfMemory);
}
} else {
if (_upb_Map_Insert(map, &ent.data.k, map->key_size, &ent.data.v,
map->val_size,
if (_upb_Map_Insert(map, &ent.k, map->key_size, &ent.v, map->val_size,
&d->arena) == kUpb_MapInsertStatus_OutOfMemory) {
_upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_OutOfMemory);
}
@ -758,14 +757,9 @@ const char* _upb_Decoder_CheckRequired(upb_Decoder* d, const char* ptr,
const upb_Message* msg,
const upb_MiniTable* m) {
UPB_ASSERT(m->UPB_PRIVATE(required_count));
if (UPB_LIKELY((d->options & kUpb_DecodeOption_CheckRequired) == 0)) {
return ptr;
}
uint64_t msg_head;
memcpy(&msg_head, msg, 8);
msg_head = upb_BigEndian64(msg_head);
if (UPB_PRIVATE(_upb_MiniTable_RequiredMask)(m) & ~msg_head) {
d->missing_required = true;
if (UPB_UNLIKELY(d->options & kUpb_DecodeOption_CheckRequired)) {
d->missing_required =
!UPB_PRIVATE(_upb_Message_IsInitializedShallow)(msg, m);
}
return ptr;
}
@ -1339,10 +1333,11 @@ const char* _upb_FastDecoder_DecodeGeneric(struct upb_Decoder* d,
}
static upb_DecodeStatus _upb_Decoder_DecodeTop(struct upb_Decoder* d,
const char* buf, void* msg,
const upb_MiniTable* l) {
if (!_upb_Decoder_TryFastDispatch(d, &buf, msg, l)) {
_upb_Decoder_DecodeMessage(d, buf, msg, l);
const char* buf,
upb_Message* msg,
const upb_MiniTable* m) {
if (!_upb_Decoder_TryFastDispatch(d, &buf, msg, m)) {
_upb_Decoder_DecodeMessage(d, buf, msg, m);
}
if (d->end_group != DECODE_NOGROUP) return kUpb_DecodeStatus_Malformed;
if (d->missing_required) return kUpb_DecodeStatus_MissingRequired;
@ -1358,11 +1353,11 @@ const char* _upb_Decoder_IsDoneFallback(upb_EpsCopyInputStream* e,
static upb_DecodeStatus upb_Decoder_Decode(upb_Decoder* const decoder,
const char* const buf,
void* const msg,
const upb_MiniTable* const l,
upb_Message* const msg,
const upb_MiniTable* const m,
upb_Arena* const arena) {
if (UPB_SETJMP(decoder->err) == 0) {
decoder->status = _upb_Decoder_DecodeTop(decoder, buf, msg, l);
decoder->status = _upb_Decoder_DecodeTop(decoder, buf, msg, m);
} else {
UPB_ASSERT(decoder->status != kUpb_DecodeStatus_Ok);
}
@ -1373,7 +1368,7 @@ static upb_DecodeStatus upb_Decoder_Decode(upb_Decoder* const decoder,
}
upb_DecodeStatus upb_Decode(const char* buf, size_t size, upb_Message* msg,
const upb_MiniTable* l,
const upb_MiniTable* m,
const upb_ExtensionRegistry* extreg, int options,
upb_Arena* arena) {
upb_Decoder decoder;
@ -1397,7 +1392,7 @@ upb_DecodeStatus upb_Decode(const char* buf, size_t size, upb_Message* msg,
// (particularly parent_or_count).
UPB_PRIVATE(_upb_Arena_SwapIn)(&decoder.arena, arena);
return upb_Decoder_Decode(&decoder, buf, msg, l, arena);
return upb_Decoder_Decode(&decoder, buf, msg, m, arena);
}
#undef OP_FIXPCK_LG2

@ -25,7 +25,6 @@
#include "upb/message/internal/array.h"
#include "upb/message/internal/extension.h"
#include "upb/message/internal/map.h"
#include "upb/message/internal/map_entry.h"
#include "upb/message/internal/map_sorter.h"
#include "upb/message/internal/tagged_ptr.h"
#include "upb/message/map.h"
@ -34,6 +33,7 @@
#include "upb/mini_table/extension.h"
#include "upb/mini_table/field.h"
#include "upb/mini_table/internal/field.h"
#include "upb/mini_table/internal/map_entry.h"
#include "upb/mini_table/internal/message.h"
#include "upb/mini_table/message.h"
#include "upb/mini_table/sub.h"
@ -424,8 +424,8 @@ static void encode_mapentry(upb_encstate* e, uint32_t number,
const upb_MiniTableField* val_field = &layout->UPB_PRIVATE(fields)[1];
size_t pre_len = e->limit - e->ptr;
size_t size;
encode_scalar(e, &ent->data.v, layout->UPB_PRIVATE(subs), val_field);
encode_scalar(e, &ent->data.k, layout->UPB_PRIVATE(subs), key_field);
encode_scalar(e, &ent->v, layout->UPB_PRIVATE(subs), val_field);
encode_scalar(e, &ent->k, layout->UPB_PRIVATE(subs), key_field);
size = (e->limit - e->ptr) - pre_len;
encode_varint(e, size);
encode_tag(e, number, kUpb_WireType_Delimited);
@ -457,8 +457,8 @@ static void encode_map(upb_encstate* e, const upb_Message* msg,
upb_value val;
while (upb_strtable_next2(&map->table, &key, &val, &iter)) {
upb_MapEntry ent;
_upb_map_fromkey(key, &ent.data.k, map->key_size);
_upb_map_fromvalue(val, &ent.data.v, map->val_size);
_upb_map_fromkey(key, &ent.k, map->key_size);
_upb_map_fromvalue(val, &ent.v, map->val_size);
encode_mapentry(e, f->UPB_PRIVATE(number), layout, &ent);
}
}
@ -548,13 +548,11 @@ static void encode_message(upb_encstate* e, const upb_Message* msg,
const upb_MiniTable* m, size_t* size) {
size_t pre_len = e->limit - e->ptr;
if ((e->options & kUpb_EncodeOption_CheckRequired) &&
m->UPB_PRIVATE(required_count)) {
uint64_t msg_head;
memcpy(&msg_head, msg, 8);
msg_head = upb_BigEndian64(msg_head);
if (UPB_PRIVATE(_upb_MiniTable_RequiredMask)(m) & ~msg_head) {
encode_err(e, kUpb_EncodeStatus_MissingRequired);
if (e->options & kUpb_EncodeOption_CheckRequired) {
if (m->UPB_PRIVATE(required_count)) {
if (!UPB_PRIVATE(_upb_Message_IsInitializedShallow)(msg, m)) {
encode_err(e, kUpb_EncodeStatus_MissingRequired);
}
}
}

@ -62,7 +62,7 @@ static const char* fastdecode_dispatch(UPB_PARSE_PARAMS) {
int overrun;
switch (upb_EpsCopyInputStream_IsDoneStatus(&d->input, ptr, &overrun)) {
case kUpb_IsDoneStatus_Done:
*(uint32_t*)msg |= hasbits; // Sync hasbits.
((uint32_t*)msg)[2] |= hasbits; // Sync hasbits.
const upb_MiniTable* m = decode_totablep(table);
return UPB_UNLIKELY(m->UPB_PRIVATE(required_count))
? _upb_Decoder_CheckRequired(d, ptr, msg, m)
@ -253,7 +253,7 @@ static void* fastdecode_getfield(upb_Decoder* d, const char* ptr,
uint8_t elem_size_lg2 = __builtin_ctz(valbytes);
upb_Array** arr_p = fastdecode_fieldmem(msg, *data);
char* begin;
*(uint32_t*)msg |= *hasbits;
((uint32_t*)msg)[2] |= *hasbits;
*hasbits = 0;
if (UPB_LIKELY(!*arr_p)) {
farr->arr = UPB_PRIVATE(_upb_Array_New)(&d->arena, 8, elem_size_lg2);
@ -869,7 +869,7 @@ TAGBYTES(r)
UPB_INLINE
upb_Message* decode_newmsg_ceil(upb_Decoder* d, const upb_MiniTable* m,
int msg_ceil_bytes) {
size_t size = m->UPB_PRIVATE(size) + sizeof(upb_Message_Internal);
size_t size = m->UPB_PRIVATE(size);
char* msg_data;
if (UPB_LIKELY(msg_ceil_bytes > 0 &&
UPB_PRIVATE(_upb_ArenaHas)(&d->arena) >= msg_ceil_bytes)) {
@ -883,7 +883,7 @@ upb_Message* decode_newmsg_ceil(upb_Decoder* d, const upb_MiniTable* m,
msg_data = (char*)upb_Arena_Malloc(&d->arena, size);
memset(msg_data, 0, size);
}
return msg_data + sizeof(upb_Message_Internal);
return (upb_Message*)msg_data;
}
typedef struct {
@ -929,7 +929,7 @@ static const char* fastdecode_tosubmsg(upb_EpsCopyInputStream* e,
sizeof(upb_Message*), card); \
\
if (card == CARD_s) { \
*(uint32_t*)msg |= hasbits; \
((uint32_t*)msg)[2] |= hasbits; \
hasbits = 0; \
} \
\

Loading…
Cancel
Save