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