File indexing completed on 2026-10-07 10:07:36
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #ifndef UPB_MESSAGE_INTERNAL_MESSAGE_H_
0016 #define UPB_MESSAGE_INTERNAL_MESSAGE_H_
0017
0018 #include <stdint.h>
0019 #include <stdlib.h>
0020 #include <string.h>
0021
0022 #include "upb/base/string_view.h"
0023 #include "upb/mem/arena.h"
0024 #include "upb/message/internal/extension.h"
0025 #include "upb/message/internal/types.h"
0026 #include "upb/mini_table/extension.h"
0027 #include "upb/mini_table/internal/message.h"
0028 #include "upb/mini_table/message.h"
0029
0030
0031 #include "upb/port/def.inc"
0032
0033 #ifdef __cplusplus
0034 extern "C" {
0035 #endif
0036
0037 extern const float kUpb_FltInfinity;
0038 extern const double kUpb_Infinity;
0039 extern const double kUpb_NaN;
0040
0041
0042
0043
0044 typedef struct upb_TaggedAuxPtr {
0045
0046
0047
0048
0049 uintptr_t ptr;
0050 } upb_TaggedAuxPtr;
0051
0052 UPB_INLINE bool upb_TaggedAuxPtr_IsNull(upb_TaggedAuxPtr ptr) {
0053 return ptr.ptr == 0;
0054 }
0055
0056 UPB_INLINE bool upb_TaggedAuxPtr_IsExtension(upb_TaggedAuxPtr ptr) {
0057 return ptr.ptr & 1;
0058 }
0059
0060 UPB_INLINE bool upb_TaggedAuxPtr_IsUnknown(upb_TaggedAuxPtr ptr) {
0061 return (ptr.ptr != 0) && ((ptr.ptr & 1) == 0);
0062 }
0063
0064 UPB_INLINE bool upb_TaggedAuxPtr_IsUnknownAliased(upb_TaggedAuxPtr ptr) {
0065 return (ptr.ptr != 0) && ((ptr.ptr & 2) == 2);
0066 }
0067
0068 UPB_INLINE upb_Extension* upb_TaggedAuxPtr_Extension(upb_TaggedAuxPtr ptr) {
0069 UPB_ASSERT(upb_TaggedAuxPtr_IsExtension(ptr));
0070 return (upb_Extension*)(ptr.ptr & ~3ULL);
0071 }
0072
0073 UPB_INLINE upb_StringView* upb_TaggedAuxPtr_UnknownData(upb_TaggedAuxPtr ptr) {
0074 UPB_ASSERT(!upb_TaggedAuxPtr_IsExtension(ptr));
0075 return (upb_StringView*)(ptr.ptr & ~3ULL);
0076 }
0077
0078 UPB_INLINE upb_TaggedAuxPtr upb_TaggedAuxPtr_Null(void) {
0079 upb_TaggedAuxPtr ptr;
0080 ptr.ptr = 0;
0081 return ptr;
0082 }
0083
0084 UPB_INLINE upb_TaggedAuxPtr
0085 upb_TaggedAuxPtr_MakeExtension(const upb_Extension* e) {
0086 upb_TaggedAuxPtr ptr;
0087 ptr.ptr = (uintptr_t)e | 1;
0088 return ptr;
0089 }
0090
0091
0092
0093
0094 UPB_INLINE upb_TaggedAuxPtr
0095 upb_TaggedAuxPtr_MakeUnknownData(const upb_StringView* sv) {
0096 upb_TaggedAuxPtr ptr;
0097 ptr.ptr = (uintptr_t)sv;
0098 return ptr;
0099 }
0100
0101
0102
0103 UPB_INLINE upb_TaggedAuxPtr
0104 upb_TaggedAuxPtr_MakeUnknownDataAliased(const upb_StringView* sv) {
0105 upb_TaggedAuxPtr ptr;
0106 ptr.ptr = (uintptr_t)sv | 2;
0107 return ptr;
0108 }
0109
0110 typedef struct upb_Message_Internal {
0111
0112 uint32_t size;
0113 uint32_t capacity;
0114
0115 upb_TaggedAuxPtr aux_data[];
0116 } upb_Message_Internal;
0117
0118 #ifdef UPB_TRACING_ENABLED
0119 UPB_API void upb_Message_LogNewMessage(const upb_MiniTable* m,
0120 const upb_Arena* arena);
0121 UPB_API void upb_Message_SetNewMessageTraceHandler(
0122 void (*handler)(const upb_MiniTable*, const upb_Arena*));
0123 #endif
0124
0125
0126 UPB_INLINE struct upb_Message* _upb_Message_New(const upb_MiniTable* m,
0127 upb_Arena* a) {
0128 UPB_PRIVATE(upb_MiniTable_CheckInvariants)(m);
0129 #ifdef UPB_TRACING_ENABLED
0130 upb_Message_LogNewMessage(m, a);
0131 #endif
0132
0133 const size_t size = m->UPB_PRIVATE(size);
0134
0135
0136 UPB_ASSUME(size % kUpb_Message_Align == 0);
0137 struct upb_Message* msg = (struct upb_Message*)upb_Arena_Malloc(a, size);
0138 if (UPB_UNLIKELY(!msg)) return NULL;
0139 memset(msg, 0, size);
0140 return msg;
0141 }
0142
0143
0144 void _upb_Message_DiscardUnknown_shallow(struct upb_Message* msg);
0145
0146 UPB_NOINLINE bool UPB_PRIVATE(_upb_Message_AddUnknownSlowPath)(
0147 struct upb_Message* msg, const char* data, size_t len, upb_Arena* arena,
0148 bool alias);
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160 UPB_INLINE bool UPB_PRIVATE(_upb_Message_AddUnknown)(struct upb_Message* msg,
0161 const char* data,
0162 size_t len,
0163 upb_Arena* arena,
0164 const char* alias_base) {
0165 UPB_ASSERT(!upb_Message_IsFrozen(msg));
0166 if (alias_base) {
0167
0168
0169 upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg);
0170 if (in && in->size) {
0171 upb_TaggedAuxPtr ptr = in->aux_data[in->size - 1];
0172 if (upb_TaggedAuxPtr_IsUnknown(ptr)) {
0173 upb_StringView* existing = upb_TaggedAuxPtr_UnknownData(ptr);
0174
0175
0176
0177
0178
0179
0180 if (data != alias_base && existing->data + existing->size == data) {
0181 existing->size += len;
0182 return true;
0183 }
0184 }
0185 }
0186 }
0187 return UPB_PRIVATE(_upb_Message_AddUnknownSlowPath)(msg, data, len, arena,
0188 alias_base != NULL);
0189 }
0190
0191
0192
0193
0194
0195 bool UPB_PRIVATE(_upb_Message_AddUnknownV)(struct upb_Message* msg,
0196 upb_Arena* arena,
0197 upb_StringView data[], size_t count);
0198
0199
0200
0201 bool UPB_PRIVATE(_upb_Message_ReserveSlot)(struct upb_Message* msg,
0202 upb_Arena* arena);
0203
0204 #define kUpb_Message_UnknownBegin 0
0205 #define kUpb_Message_ExtensionBegin 0
0206
0207 UPB_INLINE bool upb_Message_NextUnknown(const struct upb_Message* msg,
0208 upb_StringView* data, uintptr_t* iter) {
0209 const upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg);
0210 size_t i = *iter;
0211 if (in) {
0212 while (i < in->size) {
0213 upb_TaggedAuxPtr tagged_ptr = in->aux_data[i++];
0214 if (upb_TaggedAuxPtr_IsUnknown(tagged_ptr)) {
0215 *data = *upb_TaggedAuxPtr_UnknownData(tagged_ptr);
0216 *iter = i;
0217 return true;
0218 }
0219 }
0220 }
0221 data->size = 0;
0222 data->data = NULL;
0223 *iter = i;
0224 return false;
0225 }
0226
0227 UPB_INLINE bool upb_Message_HasUnknown(const struct upb_Message* msg) {
0228 upb_StringView data;
0229 uintptr_t iter = kUpb_Message_UnknownBegin;
0230 return upb_Message_NextUnknown(msg, &data, &iter);
0231 }
0232
0233 UPB_INLINE bool upb_Message_NextExtension(const struct upb_Message* msg,
0234 const upb_MiniTableExtension** out_e,
0235 upb_MessageValue* out_v,
0236 uintptr_t* iter) {
0237 const upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg);
0238 uintptr_t i = *iter;
0239 if (in) {
0240 while (i < in->size) {
0241 upb_TaggedAuxPtr tagged_ptr = in->aux_data[i++];
0242 if (upb_TaggedAuxPtr_IsExtension(tagged_ptr)) {
0243 const upb_Extension* ext = upb_TaggedAuxPtr_Extension(tagged_ptr);
0244
0245
0246 if (UPB_PRIVATE(_upb_Extension_IsEmpty)(ext)) continue;
0247
0248 *out_e = ext->ext;
0249 *out_v = ext->data;
0250 *iter = i;
0251 return true;
0252 }
0253 }
0254 }
0255 *iter = i;
0256
0257 return false;
0258 }
0259
0260 UPB_INLINE bool UPB_PRIVATE(_upb_Message_NextExtensionReverse)(
0261 const struct upb_Message* msg, const upb_MiniTableExtension** out_e,
0262 upb_MessageValue* out_v, uintptr_t* iter) {
0263 upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg);
0264 if (!in) return false;
0265 uintptr_t i = *iter;
0266 uint32_t size = in->size;
0267 while (i < size) {
0268 upb_TaggedAuxPtr tagged_ptr = in->aux_data[size - 1 - i];
0269 i++;
0270 if (!upb_TaggedAuxPtr_IsExtension(tagged_ptr)) {
0271 continue;
0272 }
0273 const upb_Extension* ext = upb_TaggedAuxPtr_Extension(tagged_ptr);
0274
0275
0276 if (UPB_PRIVATE(_upb_Extension_IsEmpty)(ext)) continue;
0277
0278 *out_e = ext->ext;
0279 *out_v = ext->data;
0280 *iter = i;
0281 return true;
0282 }
0283 *iter = i;
0284 return false;
0285 }
0286
0287 #ifdef __cplusplus
0288 }
0289 #endif
0290
0291 #include "upb/port/undef.inc"
0292
0293 #endif