Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-10-07 10:07:36

0001 // Protocol Buffers - Google's data interchange format
0002 // Copyright 2023 Google LLC.  All rights reserved.
0003 //
0004 // Use of this source code is governed by a BSD-style
0005 // license that can be found in the LICENSE file or at
0006 // https://developers.google.com/open-source/licenses/bsd
0007 
0008 /*
0009 ** Our memory representation for parsing tables and messages themselves.
0010 ** Functions in this file are used by generated code and possibly reflection.
0011 **
0012 ** The definitions in this file are internal to upb.
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 // Must be last.
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 // Internal members of a upb_Message that track unknown fields and/or
0042 // extensions. We can change this without breaking binary compatibility.
0043 
0044 typedef struct upb_TaggedAuxPtr {
0045   // Two lowest bits form a tag:
0046   // 00 - non-aliased unknown data
0047   // 10 - aliased unknown data
0048   // 01 - extension
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 // This tag means that the original allocation for this field starts with the
0092 // string view and ends with the end of the content referenced by the string
0093 // view.
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 // This tag implies no guarantee between the relationship of the string view and
0102 // the data it points to.
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   // Total number of entries set in aux_data
0112   uint32_t size;
0113   uint32_t capacity;
0114   // Tagged pointers to upb_StringView or upb_Extension
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  // UPB_TRACING_ENABLED
0124 
0125 // Inline version upb_Message_New(), for internal use.
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  // UPB_TRACING_ENABLED
0132 
0133   const size_t size = m->UPB_PRIVATE(size);
0134   // Message sizes are aligned up when constructing minitables; telling the
0135   // compiler this avoids redoing alignment on the malloc fast path
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 // Discards the unknown fields for this message only.
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 // Adds unknown data (serialized protobuf data) to the given message. The data
0151 // must represent one or more complete and well formed proto fields.
0152 //
0153 // If `alias_base` is NULL, the bytes from `data` will be copied into the
0154 // destination arena. Otherwise it must be a pointer to the beginning of the
0155 // buffer that `data` points into, which signals that the message must alias
0156 // the bytes instead of copying them. The value of `alias_base` is also used
0157 // to mark the boundary of the buffer, so that we do not inappropriately
0158 // coalesce two buffers that are separate objects but happen to be contiguous
0159 // in memory.
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     // Aliasing parse of a message with sequential unknown fields is a simple
0168     // pointer bump, so inline it.
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         // Fast path if the field we're adding is immediately after the last
0175         // added unknown field. However, we could be merging into an existing
0176         // message with an allocation that just happens to be positioned
0177         // immediately after the previous merged unknown field; this is
0178         // considered out-of-bounds and thus UB. Ensure it's in-bounds by
0179         // comparing with the original input pointer for our buffer.
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 // Adds unknown data (serialized protobuf data) to the given message.
0192 // The data is copied into the message instance. Data when concatenated together
0193 // must represent one or more complete and well formed proto fields, but the
0194 // individual spans may point only to partial fields.
0195 bool UPB_PRIVATE(_upb_Message_AddUnknownV)(struct upb_Message* msg,
0196                                            upb_Arena* arena,
0197                                            upb_StringView data[], size_t count);
0198 
0199 // Ensures at least one slot is available in the aux_data of this message.
0200 // Returns false if a reallocation is needed to satisfy the request, and fails.
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         // Empty repeated fields or maps semantically don't exist.
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     // Empty repeated fields or maps semantically don't exist.
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 } /* extern "C" */
0289 #endif
0290 
0291 #include "upb/port/undef.inc"
0292 
0293 #endif /* UPB_MESSAGE_INTERNAL_MESSAGE_H_ */