1 /*
2 * Copyright (c) 2009-2022, Google LLC
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of Google LLC nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL Google LLC BE LIABLE FOR ANY DIRECT,
20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 #ifndef UPB_MESSAGE_ACCESSORS_H_
29 #define UPB_MESSAGE_ACCESSORS_H_
30
31 #include "upb/base/descriptor_constants.h"
32 #include "upb/collections/array.h"
33 #include "upb/collections/array_internal.h"
34 #include "upb/collections/map.h"
35 #include "upb/collections/map_internal.h"
36 #include "upb/message/accessors_internal.h"
37 #include "upb/message/extension_internal.h"
38 #include "upb/message/internal.h"
39 #include "upb/mini_table/common.h"
40 #include "upb/mini_table/enum_internal.h"
41 #include "upb/mini_table/field_internal.h"
42
43 // Must be last.
44 #include "upb/port/def.inc"
45
46 #ifdef __cplusplus
47 extern "C" {
48 #endif
49
upb_Message_ClearField(upb_Message * msg,const upb_MiniTableField * field)50 UPB_API_INLINE void upb_Message_ClearField(upb_Message* msg,
51 const upb_MiniTableField* field) {
52 if (upb_MiniTableField_IsExtension(field)) {
53 const upb_MiniTableExtension* ext = (const upb_MiniTableExtension*)field;
54 _upb_Message_ClearExtensionField(msg, ext);
55 } else {
56 _upb_Message_ClearNonExtensionField(msg, field);
57 }
58 }
59
upb_Message_HasField(const upb_Message * msg,const upb_MiniTableField * field)60 UPB_API_INLINE bool upb_Message_HasField(const upb_Message* msg,
61 const upb_MiniTableField* field) {
62 if (upb_MiniTableField_IsExtension(field)) {
63 const upb_MiniTableExtension* ext = (const upb_MiniTableExtension*)field;
64 return _upb_Message_HasExtensionField(msg, ext);
65 } else {
66 return _upb_Message_HasNonExtensionField(msg, field);
67 }
68 }
69
upb_Message_WhichOneofFieldNumber(const upb_Message * message,const upb_MiniTableField * oneof_field)70 UPB_API_INLINE uint32_t upb_Message_WhichOneofFieldNumber(
71 const upb_Message* message, const upb_MiniTableField* oneof_field) {
72 UPB_ASSUME(_upb_MiniTableField_InOneOf(oneof_field));
73 return _upb_getoneofcase_field(message, oneof_field);
74 }
75
upb_Message_GetBool(const upb_Message * msg,const upb_MiniTableField * field,bool default_val)76 UPB_API_INLINE bool upb_Message_GetBool(const upb_Message* msg,
77 const upb_MiniTableField* field,
78 bool default_val) {
79 UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_Bool);
80 UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_1Byte);
81 UPB_ASSUME(!upb_IsRepeatedOrMap(field));
82 bool ret;
83 _upb_Message_GetField(msg, field, &default_val, &ret);
84 return ret;
85 }
86
upb_Message_SetBool(upb_Message * msg,const upb_MiniTableField * field,bool value,upb_Arena * a)87 UPB_API_INLINE bool upb_Message_SetBool(upb_Message* msg,
88 const upb_MiniTableField* field,
89 bool value, upb_Arena* a) {
90 UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_Bool);
91 UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_1Byte);
92 UPB_ASSUME(!upb_IsRepeatedOrMap(field));
93 return _upb_Message_SetField(msg, field, &value, a);
94 }
95
upb_Message_GetInt32(const upb_Message * msg,const upb_MiniTableField * field,int32_t default_val)96 UPB_API_INLINE int32_t upb_Message_GetInt32(const upb_Message* msg,
97 const upb_MiniTableField* field,
98 int32_t default_val) {
99 UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_Int32 ||
100 upb_MiniTableField_CType(field) == kUpb_CType_Enum);
101 UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_4Byte);
102 UPB_ASSUME(!upb_IsRepeatedOrMap(field));
103 int32_t ret;
104 _upb_Message_GetField(msg, field, &default_val, &ret);
105 return ret;
106 }
107
upb_Message_SetInt32(upb_Message * msg,const upb_MiniTableField * field,int32_t value,upb_Arena * a)108 UPB_API_INLINE bool upb_Message_SetInt32(upb_Message* msg,
109 const upb_MiniTableField* field,
110 int32_t value, upb_Arena* a) {
111 UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_Int32 ||
112 upb_MiniTableField_CType(field) == kUpb_CType_Enum);
113 UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_4Byte);
114 UPB_ASSUME(!upb_IsRepeatedOrMap(field));
115 return _upb_Message_SetField(msg, field, &value, a);
116 }
117
upb_Message_GetUInt32(const upb_Message * msg,const upb_MiniTableField * field,uint32_t default_val)118 UPB_API_INLINE uint32_t upb_Message_GetUInt32(const upb_Message* msg,
119 const upb_MiniTableField* field,
120 uint32_t default_val) {
121 UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_UInt32);
122 UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_4Byte);
123 UPB_ASSUME(!upb_IsRepeatedOrMap(field));
124 uint32_t ret;
125 _upb_Message_GetField(msg, field, &default_val, &ret);
126 return ret;
127 }
128
upb_Message_SetUInt32(upb_Message * msg,const upb_MiniTableField * field,uint32_t value,upb_Arena * a)129 UPB_API_INLINE bool upb_Message_SetUInt32(upb_Message* msg,
130 const upb_MiniTableField* field,
131 uint32_t value, upb_Arena* a) {
132 UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_UInt32);
133 UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_4Byte);
134 UPB_ASSUME(!upb_IsRepeatedOrMap(field));
135 return _upb_Message_SetField(msg, field, &value, a);
136 }
137
upb_Message_SetClosedEnum(upb_Message * msg,const upb_MiniTable * msg_mini_table,const upb_MiniTableField * field,int32_t value)138 UPB_API_INLINE void upb_Message_SetClosedEnum(
139 upb_Message* msg, const upb_MiniTable* msg_mini_table,
140 const upb_MiniTableField* field, int32_t value) {
141 UPB_ASSERT(upb_MiniTableField_IsClosedEnum(field));
142 UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_4Byte);
143 UPB_ASSUME(!upb_IsRepeatedOrMap(field));
144 UPB_ASSERT(upb_MiniTableEnum_CheckValue(
145 upb_MiniTable_GetSubEnumTable(msg_mini_table, field), value));
146 _upb_Message_SetNonExtensionField(msg, field, &value);
147 }
148
upb_Message_GetInt64(const upb_Message * msg,const upb_MiniTableField * field,uint64_t default_val)149 UPB_API_INLINE int64_t upb_Message_GetInt64(const upb_Message* msg,
150 const upb_MiniTableField* field,
151 uint64_t default_val) {
152 UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_Int64);
153 UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_8Byte);
154 UPB_ASSUME(!upb_IsRepeatedOrMap(field));
155 int64_t ret;
156 _upb_Message_GetField(msg, field, &default_val, &ret);
157 return ret;
158 }
159
upb_Message_SetInt64(upb_Message * msg,const upb_MiniTableField * field,int64_t value,upb_Arena * a)160 UPB_API_INLINE bool upb_Message_SetInt64(upb_Message* msg,
161 const upb_MiniTableField* field,
162 int64_t value, upb_Arena* a) {
163 UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_Int64);
164 UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_8Byte);
165 UPB_ASSUME(!upb_IsRepeatedOrMap(field));
166 return _upb_Message_SetField(msg, field, &value, a);
167 }
168
upb_Message_GetUInt64(const upb_Message * msg,const upb_MiniTableField * field,uint64_t default_val)169 UPB_API_INLINE uint64_t upb_Message_GetUInt64(const upb_Message* msg,
170 const upb_MiniTableField* field,
171 uint64_t default_val) {
172 UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_UInt64);
173 UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_8Byte);
174 UPB_ASSUME(!upb_IsRepeatedOrMap(field));
175 uint64_t ret;
176 _upb_Message_GetField(msg, field, &default_val, &ret);
177 return ret;
178 }
179
upb_Message_SetUInt64(upb_Message * msg,const upb_MiniTableField * field,uint64_t value,upb_Arena * a)180 UPB_API_INLINE bool upb_Message_SetUInt64(upb_Message* msg,
181 const upb_MiniTableField* field,
182 uint64_t value, upb_Arena* a) {
183 UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_UInt64);
184 UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_8Byte);
185 UPB_ASSUME(!upb_IsRepeatedOrMap(field));
186 return _upb_Message_SetField(msg, field, &value, a);
187 }
188
upb_Message_GetFloat(const upb_Message * msg,const upb_MiniTableField * field,float default_val)189 UPB_API_INLINE float upb_Message_GetFloat(const upb_Message* msg,
190 const upb_MiniTableField* field,
191 float default_val) {
192 UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_Float);
193 UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_4Byte);
194 UPB_ASSUME(!upb_IsRepeatedOrMap(field));
195 float ret;
196 _upb_Message_GetField(msg, field, &default_val, &ret);
197 return ret;
198 }
199
upb_Message_SetFloat(upb_Message * msg,const upb_MiniTableField * field,float value,upb_Arena * a)200 UPB_API_INLINE bool upb_Message_SetFloat(upb_Message* msg,
201 const upb_MiniTableField* field,
202 float value, upb_Arena* a) {
203 UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_Float);
204 UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_4Byte);
205 UPB_ASSUME(!upb_IsRepeatedOrMap(field));
206 return _upb_Message_SetField(msg, field, &value, a);
207 }
208
upb_Message_GetDouble(const upb_Message * msg,const upb_MiniTableField * field,double default_val)209 UPB_API_INLINE double upb_Message_GetDouble(const upb_Message* msg,
210 const upb_MiniTableField* field,
211 double default_val) {
212 UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_Double);
213 UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_8Byte);
214 UPB_ASSUME(!upb_IsRepeatedOrMap(field));
215 double ret;
216 _upb_Message_GetField(msg, field, &default_val, &ret);
217 return ret;
218 }
219
upb_Message_SetDouble(upb_Message * msg,const upb_MiniTableField * field,double value,upb_Arena * a)220 UPB_API_INLINE bool upb_Message_SetDouble(upb_Message* msg,
221 const upb_MiniTableField* field,
222 double value, upb_Arena* a) {
223 UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_Double);
224 UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_8Byte);
225 UPB_ASSUME(!upb_IsRepeatedOrMap(field));
226 return _upb_Message_SetField(msg, field, &value, a);
227 }
228
229 UPB_API_INLINE upb_StringView
upb_Message_GetString(const upb_Message * msg,const upb_MiniTableField * field,upb_StringView def_val)230 upb_Message_GetString(const upb_Message* msg, const upb_MiniTableField* field,
231 upb_StringView def_val) {
232 UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_String ||
233 upb_MiniTableField_CType(field) == kUpb_CType_Bytes);
234 UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_StringView);
235 UPB_ASSUME(!upb_IsRepeatedOrMap(field));
236 upb_StringView ret;
237 _upb_Message_GetField(msg, field, &def_val, &ret);
238 return ret;
239 }
240
upb_Message_SetString(upb_Message * msg,const upb_MiniTableField * field,upb_StringView value,upb_Arena * a)241 UPB_API_INLINE bool upb_Message_SetString(upb_Message* msg,
242 const upb_MiniTableField* field,
243 upb_StringView value, upb_Arena* a) {
244 UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_String ||
245 upb_MiniTableField_CType(field) == kUpb_CType_Bytes);
246 UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_StringView);
247 UPB_ASSUME(!upb_IsRepeatedOrMap(field));
248 return _upb_Message_SetField(msg, field, &value, a);
249 }
250
upb_Message_GetMessage(const upb_Message * msg,const upb_MiniTableField * field,upb_Message * default_val)251 UPB_API_INLINE const upb_Message* upb_Message_GetMessage(
252 const upb_Message* msg, const upb_MiniTableField* field,
253 upb_Message* default_val) {
254 UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_Message);
255 UPB_ASSUME(_upb_MiniTableField_GetRep(field) ==
256 UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte));
257 UPB_ASSUME(!upb_IsRepeatedOrMap(field));
258 upb_Message* ret;
259 _upb_Message_GetNonExtensionField(msg, field, &default_val, &ret);
260 return ret;
261 }
262
upb_Message_SetMessage(upb_Message * msg,const upb_MiniTable * mini_table,const upb_MiniTableField * field,upb_Message * sub_message)263 UPB_API_INLINE void upb_Message_SetMessage(upb_Message* msg,
264 const upb_MiniTable* mini_table,
265 const upb_MiniTableField* field,
266 upb_Message* sub_message) {
267 UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_Message);
268 UPB_ASSUME(_upb_MiniTableField_GetRep(field) ==
269 UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte));
270 UPB_ASSUME(!upb_IsRepeatedOrMap(field));
271 UPB_ASSERT(mini_table->subs[field->UPB_PRIVATE(submsg_index)].submsg);
272 _upb_Message_SetNonExtensionField(msg, field, &sub_message);
273 }
274
upb_Message_GetOrCreateMutableMessage(upb_Message * msg,const upb_MiniTable * mini_table,const upb_MiniTableField * field,upb_Arena * arena)275 UPB_API_INLINE upb_Message* upb_Message_GetOrCreateMutableMessage(
276 upb_Message* msg, const upb_MiniTable* mini_table,
277 const upb_MiniTableField* field, upb_Arena* arena) {
278 UPB_ASSERT(arena);
279 UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_Message);
280 upb_Message* sub_message = *UPB_PTR_AT(msg, field->offset, upb_Message*);
281 if (!sub_message) {
282 const upb_MiniTable* sub_mini_table =
283 mini_table->subs[field->UPB_PRIVATE(submsg_index)].submsg;
284 UPB_ASSERT(sub_mini_table);
285 sub_message = _upb_Message_New(sub_mini_table, arena);
286 *UPB_PTR_AT(msg, field->offset, upb_Message*) = sub_message;
287 _upb_Message_SetPresence(msg, field);
288 }
289 return sub_message;
290 }
291
upb_Message_GetArray(const upb_Message * msg,const upb_MiniTableField * field)292 UPB_API_INLINE const upb_Array* upb_Message_GetArray(
293 const upb_Message* msg, const upb_MiniTableField* field) {
294 _upb_MiniTableField_CheckIsArray(field);
295 upb_Array* ret;
296 const upb_Array* default_val = NULL;
297 _upb_Message_GetNonExtensionField(msg, field, &default_val, &ret);
298 return ret;
299 }
300
upb_Message_GetMutableArray(upb_Message * msg,const upb_MiniTableField * field)301 UPB_API_INLINE upb_Array* upb_Message_GetMutableArray(
302 upb_Message* msg, const upb_MiniTableField* field) {
303 _upb_MiniTableField_CheckIsArray(field);
304 return (upb_Array*)upb_Message_GetArray(msg, field);
305 }
306
upb_Message_GetOrCreateMutableArray(upb_Message * msg,const upb_MiniTableField * field,upb_Arena * arena)307 UPB_API_INLINE upb_Array* upb_Message_GetOrCreateMutableArray(
308 upb_Message* msg, const upb_MiniTableField* field, upb_Arena* arena) {
309 UPB_ASSERT(arena);
310 _upb_MiniTableField_CheckIsArray(field);
311 upb_Array* array = upb_Message_GetMutableArray(msg, field);
312 if (!array) {
313 array = _upb_Array_New(arena, 4, _upb_MiniTable_ElementSizeLg2(field));
314 // Check again due to: https://godbolt.org/z/7WfaoKG1r
315 _upb_MiniTableField_CheckIsArray(field);
316 _upb_Message_SetField(msg, field, &array, arena);
317 }
318 return array;
319 }
320
upb_Message_ResizeArrayUninitialized(upb_Message * msg,const upb_MiniTableField * field,size_t size,upb_Arena * arena)321 UPB_INLINE upb_Array* upb_Message_ResizeArrayUninitialized(
322 upb_Message* msg, const upb_MiniTableField* field, size_t size,
323 upb_Arena* arena) {
324 _upb_MiniTableField_CheckIsArray(field);
325 upb_Array* arr = upb_Message_GetOrCreateMutableArray(msg, field, arena);
326 if (!arr || !_upb_Array_ResizeUninitialized(arr, size, arena)) return NULL;
327 return arr;
328 }
329
330 // TODO: remove, migrate users to upb_Message_ResizeArrayUninitialized(), which
331 // has the same semantics but a clearer name. Alternatively, if users want an
332 // initialized variant, we can also offer that.
upb_Message_ResizeArray(upb_Message * msg,const upb_MiniTableField * field,size_t size,upb_Arena * arena)333 UPB_API_INLINE void* upb_Message_ResizeArray(upb_Message* msg,
334 const upb_MiniTableField* field,
335 size_t size, upb_Arena* arena) {
336 _upb_MiniTableField_CheckIsArray(field);
337 upb_Array* arr =
338 upb_Message_ResizeArrayUninitialized(msg, field, size, arena);
339 return _upb_array_ptr(arr);
340 }
341
upb_Message_GetMap(const upb_Message * msg,const upb_MiniTableField * field)342 UPB_API_INLINE const upb_Map* upb_Message_GetMap(
343 const upb_Message* msg, const upb_MiniTableField* field) {
344 _upb_MiniTableField_CheckIsMap(field);
345 upb_Map* ret;
346 const upb_Map* default_val = NULL;
347 _upb_Message_GetNonExtensionField(msg, field, &default_val, &ret);
348 return ret;
349 }
350
upb_Message_GetOrCreateMutableMap(upb_Message * msg,const upb_MiniTable * map_entry_mini_table,const upb_MiniTableField * field,upb_Arena * arena)351 UPB_API_INLINE upb_Map* upb_Message_GetOrCreateMutableMap(
352 upb_Message* msg, const upb_MiniTable* map_entry_mini_table,
353 const upb_MiniTableField* field, upb_Arena* arena) {
354 UPB_ASSUME(upb_MiniTableField_CType(field) == kUpb_CType_Message);
355 const upb_MiniTableField* map_entry_key_field =
356 &map_entry_mini_table->fields[0];
357 const upb_MiniTableField* map_entry_value_field =
358 &map_entry_mini_table->fields[1];
359 return _upb_Message_GetOrCreateMutableMap(
360 msg, field,
361 _upb_Map_CTypeSize(upb_MiniTableField_CType(map_entry_key_field)),
362 _upb_Map_CTypeSize(upb_MiniTableField_CType(map_entry_value_field)),
363 arena);
364 }
365
366 // Updates a map entry given an entry message.
367 upb_MapInsertStatus upb_Message_InsertMapEntry(upb_Map* map,
368 const upb_MiniTable* mini_table,
369 const upb_MiniTableField* field,
370 upb_Message* map_entry_message,
371 upb_Arena* arena);
372
373 #ifdef __cplusplus
374 } /* extern "C" */
375 #endif
376
377 #include "upb/port/undef.inc"
378
379 #endif // UPB_MESSAGE_ACCESSORS_H_
380