WPILibC++ 2027.0.0-alpha-3
Loading...
Searching...
No Matches
message.h
Go to the documentation of this file.
1// Protocol Buffers - Google's data interchange format
2// Copyright 2023 Google LLC. All rights reserved.
3//
4// Use of this source code is governed by a BSD-style
5// license that can be found in the LICENSE file or at
6// https://developers.google.com/open-source/licenses/bsd
7
8/*
9** Our memory representation for parsing tables and messages themselves.
10** Functions in this file are used by generated code and possibly reflection.
11**
12** The definitions in this file are internal to upb.
13**/
14
15#ifndef UPB_MESSAGE_INTERNAL_MESSAGE_H_
16#define UPB_MESSAGE_INTERNAL_MESSAGE_H_
17
18#include <stdint.h>
19#include <stdlib.h>
20#include <string.h>
21
23#include "upb/mem/arena.h"
29
30// Must be last.
31#include "upb/port/def.inc"
32
33#ifdef __cplusplus
34extern "C" {
35#endif
36
37extern const float kUpb_FltInfinity;
38extern const double kUpb_Infinity;
39extern const double kUpb_NaN;
40
41// Internal members of a upb_Message that track unknown fields and/or
42// extensions. We can change this without breaking binary compatibility.
43
44typedef struct upb_TaggedAuxPtr {
45 // Two lowest bits form a tag:
46 // 00 - non-aliased unknown data
47 // 10 - aliased unknown data
48 // 01 - extension
49 uintptr_t ptr;
51
55
59
61 return (ptr.ptr != 0) && ((ptr.ptr & 1) == 0);
62}
63
65 return (ptr.ptr != 0) && ((ptr.ptr & 2) == 2);
66}
67
72
77
83
87 ptr.ptr = (uintptr_t)e | 1;
88 return ptr;
89}
90
91// This tag means that the original allocation for this field starts with the
92// string view and ends with the end of the content referenced by the string
93// view.
97 ptr.ptr = (uintptr_t)sv;
98 return ptr;
99}
100
101// This tag implies no guarantee between the relationship of the string view and
102// the data it points to.
106 ptr.ptr = (uintptr_t)sv | 2;
107 return ptr;
108}
109
110typedef struct upb_Message_Internal {
111 // Total number of entries set in aux_data
112 uint32_t size;
113 uint32_t capacity;
114 // Tagged pointers to upb_StringView or upb_Extension
117
118#ifdef UPB_TRACING_ENABLED
119UPB_API void upb_Message_LogNewMessage(const upb_MiniTable* m,
120 const upb_Arena* arena);
121UPB_API void upb_Message_SetNewMessageTraceHandler(
122 void (*handler)(const upb_MiniTable*, const upb_Arena*));
123#endif // UPB_TRACING_ENABLED
124
125// Inline version upb_Message_New(), for internal use.
127 upb_Arena* a) {
129#ifdef UPB_TRACING_ENABLED
130 upb_Message_LogNewMessage(m, a);
131#endif // UPB_TRACING_ENABLED
132
133 const size_t size = m->UPB_PRIVATE(size);
134 // Message sizes are aligned up when constructing minitables; telling the
135 // compiler this avoids redoing alignment on the malloc fast path
136 UPB_ASSUME(size % kUpb_Message_Align == 0);
137 struct upb_Message* msg = (struct upb_Message*)upb_Arena_Malloc(a, size);
138 if (UPB_UNLIKELY(!msg)) return NULL;
139 memset(msg, 0, size);
140 return msg;
141}
142
143// Discards the unknown fields for this message only.
145
147 struct upb_Message* msg, const char* data, size_t len, upb_Arena* arena,
148 bool alias);
149
150// Adds unknown data (serialized protobuf data) to the given message. The data
151// must represent one or more complete and well formed proto fields.
152//
153// If `alias_base` is NULL, the bytes from `data` will be copied into the
154// destination arena. Otherwise it must be a pointer to the beginning of the
155// buffer that `data` points into, which signals that the message must alias
156// the bytes instead of copying them. The value of `alias_base` is also used
157// to mark the boundary of the buffer, so that we do not inappropriately
158// coalesce two buffers that are separate objects but happen to be contiguous
159// in memory.
161 const char* data,
162 size_t len,
163 upb_Arena* arena,
164 const char* alias_base) {
166 if (alias_base) {
167 // Aliasing parse of a message with sequential unknown fields is a simple
168 // pointer bump, so inline it.
170 if (in && in->size) {
171 upb_TaggedAuxPtr ptr = in->aux_data[in->size - 1];
174 // Fast path if the field we're adding is immediately after the last
175 // added unknown field. However, we could be merging into an existing
176 // message with an allocation that just happens to be positioned
177 // immediately after the previous merged unknown field; this is
178 // considered out-of-bounds and thus UB. Ensure it's in-bounds by
179 // comparing with the original input pointer for our buffer.
180 if (data != alias_base && existing->data + existing->size == data) {
181 existing->size += len;
182 return true;
183 }
184 }
185 }
186 }
187 return UPB_PRIVATE(_upb_Message_AddUnknownSlowPath)(msg, data, len, arena,
188 alias_base != NULL);
189}
190
191// Adds unknown data (serialized protobuf data) to the given message.
192// The data is copied into the message instance. Data when concatenated together
193// must represent one or more complete and well formed proto fields, but the
194// individual spans may point only to partial fields.
196 upb_Arena* arena,
197 upb_StringView data[], size_t count);
198
199// Ensures at least one slot is available in the aux_data of this message.
200// Returns false if a reallocation is needed to satisfy the request, and fails.
202 upb_Arena* arena);
203
204#define kUpb_Message_UnknownBegin 0
205#define kUpb_Message_ExtensionBegin 0
206
208 upb_StringView* data, uintptr_t* iter) {
210 size_t i = *iter;
211 if (in) {
212 while (i < in->size) {
213 upb_TaggedAuxPtr tagged_ptr = in->aux_data[i++];
214 if (upb_TaggedAuxPtr_IsUnknown(tagged_ptr)) {
215 *data = *upb_TaggedAuxPtr_UnknownData(tagged_ptr);
216 *iter = i;
217 return true;
218 }
219 }
220 }
221 data->size = 0;
222 data->data = NULL;
223 *iter = i;
224 return false;
225}
226
228 upb_StringView data;
229 uintptr_t iter = kUpb_Message_UnknownBegin;
230 return upb_Message_NextUnknown(msg, &data, &iter);
231}
232
234 const upb_MiniTableExtension** out_e,
235 upb_MessageValue* out_v,
236 uintptr_t* iter) {
238 uintptr_t i = *iter;
239 if (in) {
240 while (i < in->size) {
241 upb_TaggedAuxPtr tagged_ptr = in->aux_data[i++];
242 if (upb_TaggedAuxPtr_IsExtension(tagged_ptr)) {
243 const upb_Extension* ext = upb_TaggedAuxPtr_Extension(tagged_ptr);
244
245 // Empty repeated fields or maps semantically don't exist.
246 if (UPB_PRIVATE(_upb_Extension_IsEmpty)(ext)) continue;
247
248 *out_e = ext->ext;
249 *out_v = ext->data;
250 *iter = i;
251 return true;
252 }
253 }
254 }
255 *iter = i;
256
257 return false;
258}
259
261 const struct upb_Message* msg, const upb_MiniTableExtension** out_e,
262 upb_MessageValue* out_v, uintptr_t* iter) {
264 if (!in) return false;
265 uintptr_t i = *iter;
266 uint32_t size = in->size;
267 while (i < size) {
268 upb_TaggedAuxPtr tagged_ptr = in->aux_data[size - 1 - i];
269 i++;
270 if (!upb_TaggedAuxPtr_IsExtension(tagged_ptr)) {
271 continue;
272 }
273 const upb_Extension* ext = upb_TaggedAuxPtr_Extension(tagged_ptr);
274
275 // Empty repeated fields or maps semantically don't exist.
276 if (UPB_PRIVATE(_upb_Extension_IsEmpty)(ext)) continue;
277
278 *out_e = ext->ext;
279 *out_v = ext->data;
280 *iter = i;
281 return true;
282 }
283 *iter = i;
284 return false;
285}
286
287#ifdef __cplusplus
288} /* extern "C" */
289#endif
290
291#include "upb/port/undef.inc"
292
293#endif /* UPB_MESSAGE_INTERNAL_MESSAGE_H_ */
#define UPB_UNLIKELY(x)
Definition def.inc:265
#define UPB_ASSUME(expr)
Definition def.inc:319
#define UPB_ASSERT(expr)
Definition def.inc:329
#define UPB_PRIVATE(x)
Definition def.inc:393
#define UPB_NOINLINE
Definition def.inc:289
#define UPB_INLINE
Definition def.inc:144
#define UPB_API
Definition def.inc:162
auto ptr(T p) -> const void *
Converts p to const void* for pointer formatting.
Definition format.h:3963
UPB_API_INLINE void * upb_Arena_Malloc(struct upb_Arena *a, size_t size)
Definition arena.h:65
UPB_INLINE bool UPB_PRIVATE _upb_Extension_IsEmpty(const upb_Extension *ext)
Definition extension.h:53
UPB_INLINE bool upb_Message_HasUnknown(const struct upb_Message *msg)
Definition message.h:227
bool UPB_PRIVATE _upb_Message_ReserveSlot(struct upb_Message *msg, upb_Arena *arena)
const double kUpb_NaN
UPB_INLINE bool upb_Message_NextExtension(const struct upb_Message *msg, const upb_MiniTableExtension **out_e, upb_MessageValue *out_v, uintptr_t *iter)
Definition message.h:233
UPB_INLINE bool upb_TaggedAuxPtr_IsUnknownAliased(upb_TaggedAuxPtr ptr)
Definition message.h:64
UPB_INLINE upb_TaggedAuxPtr upb_TaggedAuxPtr_MakeExtension(const upb_Extension *e)
Definition message.h:85
const float kUpb_FltInfinity
UPB_NOINLINE bool UPB_PRIVATE _upb_Message_AddUnknownSlowPath(struct upb_Message *msg, const char *data, size_t len, upb_Arena *arena, bool alias)
#define kUpb_Message_UnknownBegin
Definition message.h:204
UPB_INLINE bool upb_TaggedAuxPtr_IsExtension(upb_TaggedAuxPtr ptr)
Definition message.h:56
UPB_INLINE bool upb_TaggedAuxPtr_IsNull(upb_TaggedAuxPtr ptr)
Definition message.h:52
void _upb_Message_DiscardUnknown_shallow(struct upb_Message *msg)
struct upb_TaggedAuxPtr upb_TaggedAuxPtr
bool UPB_PRIVATE _upb_Message_AddUnknownV(struct upb_Message *msg, upb_Arena *arena, upb_StringView data[], size_t count)
UPB_INLINE bool UPB_PRIVATE _upb_Message_AddUnknown(struct upb_Message *msg, const char *data, size_t len, upb_Arena *arena, const char *alias_base)
Definition message.h:160
UPB_INLINE upb_TaggedAuxPtr upb_TaggedAuxPtr_MakeUnknownData(const upb_StringView *sv)
Definition message.h:95
UPB_INLINE bool UPB_PRIVATE _upb_Message_NextExtensionReverse(const struct upb_Message *msg, const upb_MiniTableExtension **out_e, upb_MessageValue *out_v, uintptr_t *iter)
Definition message.h:260
UPB_INLINE upb_TaggedAuxPtr upb_TaggedAuxPtr_MakeUnknownDataAliased(const upb_StringView *sv)
Definition message.h:104
struct upb_Message_Internal upb_Message_Internal
UPB_INLINE bool upb_TaggedAuxPtr_IsUnknown(upb_TaggedAuxPtr ptr)
Definition message.h:60
UPB_INLINE bool upb_Message_NextUnknown(const struct upb_Message *msg, upb_StringView *data, uintptr_t *iter)
Definition message.h:207
UPB_INLINE upb_StringView * upb_TaggedAuxPtr_UnknownData(upb_TaggedAuxPtr ptr)
Definition message.h:73
const double kUpb_Infinity
UPB_INLINE upb_TaggedAuxPtr upb_TaggedAuxPtr_Null(void)
Definition message.h:78
UPB_INLINE upb_Extension * upb_TaggedAuxPtr_Extension(upb_TaggedAuxPtr ptr)
Definition message.h:68
UPB_INLINE struct upb_Message * _upb_Message_New(const upb_MiniTable *m, upb_Arena *a)
Definition message.h:126
@ kUpb_Message_Align
Definition message.h:46
UPB_INLINE void UPB_PRIVATE upb_MiniTable_CheckInvariants(const struct upb_MiniTable *mt)
Definition message.h:85
Definition arena.h:29
Definition extension.h:32
const upb_MiniTableExtension * ext
Definition extension.h:33
upb_MessageValue data
Definition extension.h:34
Definition message.h:110
upb_TaggedAuxPtr aux_data[]
Definition message.h:115
uint32_t capacity
Definition message.h:113
uint32_t size
Definition message.h:112
Definition types.h:18
Definition extension.h:21
Definition message.h:54
const upb_MiniTableSubInternal * UPB_PRIVATE(subs)
Definition string_view.h:23
const char * data
Definition string_view.h:24
size_t size
Definition string_view.h:25
Definition message.h:44
uintptr_t ptr
Definition message.h:49
Definition value.h:27
UPB_API_INLINE bool upb_Message_IsFrozen(const struct upb_Message *msg)
Definition types.h:34
UPB_INLINE struct upb_Message_Internal *UPB_PRIVATE _upb_Message_GetInternal(const struct upb_Message *msg)
Definition types.h:38