• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "upb/reflection/message.h"
9 
10 #include <stdint.h>
11 #include <string.h>
12 
13 #include "upb/mem/arena.h"
14 #include "upb/message/accessors.h"
15 #include "upb/message/array.h"
16 #include "upb/message/internal/extension.h"
17 #include "upb/message/internal/message.h"
18 #include "upb/message/map.h"
19 #include "upb/message/message.h"
20 #include "upb/mini_table/extension.h"
21 #include "upb/mini_table/field.h"
22 #include "upb/mini_table/internal/field.h"
23 #include "upb/mini_table/internal/message.h"
24 #include "upb/mini_table/message.h"
25 #include "upb/reflection/def.h"
26 #include "upb/reflection/def_pool.h"
27 #include "upb/reflection/message_def.h"
28 #include "upb/reflection/oneof_def.h"
29 
30 // Must be last.
31 #include "upb/port/def.inc"
32 
upb_Message_HasFieldByDef(const upb_Message * msg,const upb_FieldDef * f)33 bool upb_Message_HasFieldByDef(const upb_Message* msg, const upb_FieldDef* f) {
34   const upb_MiniTableField* m_f = upb_FieldDef_MiniTable(f);
35   UPB_ASSERT(upb_FieldDef_HasPresence(f));
36 
37   if (upb_MiniTableField_IsExtension(m_f)) {
38     return upb_Message_HasExtension(msg, (const upb_MiniTableExtension*)m_f);
39   } else {
40     return upb_Message_HasBaseField(msg, m_f);
41   }
42 }
43 
upb_Message_WhichOneofByDef(const upb_Message * msg,const upb_OneofDef * o)44 const upb_FieldDef* upb_Message_WhichOneofByDef(const upb_Message* msg,
45                                                 const upb_OneofDef* o) {
46   const upb_FieldDef* f = upb_OneofDef_Field(o, 0);
47   if (upb_OneofDef_IsSynthetic(o)) {
48     UPB_ASSERT(upb_OneofDef_FieldCount(o) == 1);
49     return upb_Message_HasFieldByDef(msg, f) ? f : NULL;
50   } else {
51     const upb_MiniTableField* field = upb_FieldDef_MiniTable(f);
52     uint32_t oneof_case = upb_Message_WhichOneofFieldNumber(msg, field);
53     f = oneof_case ? upb_OneofDef_LookupNumber(o, oneof_case) : NULL;
54     UPB_ASSERT((f != NULL) == (oneof_case != 0));
55     return f;
56   }
57 }
58 
upb_Message_GetFieldByDef(const upb_Message * msg,const upb_FieldDef * f)59 upb_MessageValue upb_Message_GetFieldByDef(const upb_Message* msg,
60                                            const upb_FieldDef* f) {
61   upb_MessageValue default_val = upb_FieldDef_Default(f);
62   return upb_Message_GetField(msg, upb_FieldDef_MiniTable(f), default_val);
63 }
64 
upb_Message_Mutable(upb_Message * msg,const upb_FieldDef * f,upb_Arena * a)65 upb_MutableMessageValue upb_Message_Mutable(upb_Message* msg,
66                                             const upb_FieldDef* f,
67                                             upb_Arena* a) {
68   UPB_ASSERT(!upb_Message_IsFrozen(msg));
69   UPB_ASSERT(upb_FieldDef_IsSubMessage(f) || upb_FieldDef_IsRepeated(f));
70   if (upb_FieldDef_HasPresence(f) && !upb_Message_HasFieldByDef(msg, f)) {
71     // We need to skip the upb_Message_GetFieldByDef() call in this case.
72     goto make;
73   }
74 
75   upb_MessageValue val = upb_Message_GetFieldByDef(msg, f);
76   if (val.array_val) {
77     return (upb_MutableMessageValue){.array = (upb_Array*)val.array_val};
78   }
79 
80   upb_MutableMessageValue ret;
81 make:
82   if (!a) return (upb_MutableMessageValue){.array = NULL};
83   if (upb_FieldDef_IsMap(f)) {
84     const upb_MessageDef* entry = upb_FieldDef_MessageSubDef(f);
85     const upb_FieldDef* key =
86         upb_MessageDef_FindFieldByNumber(entry, kUpb_MapEntry_KeyFieldNumber);
87     const upb_FieldDef* value =
88         upb_MessageDef_FindFieldByNumber(entry, kUpb_MapEntry_ValueFieldNumber);
89     ret.map =
90         upb_Map_New(a, upb_FieldDef_CType(key), upb_FieldDef_CType(value));
91   } else if (upb_FieldDef_IsRepeated(f)) {
92     ret.array = upb_Array_New(a, upb_FieldDef_CType(f));
93   } else {
94     UPB_ASSERT(upb_FieldDef_IsSubMessage(f));
95     const upb_MessageDef* m = upb_FieldDef_MessageSubDef(f);
96     ret.msg = upb_Message_New(upb_MessageDef_MiniTable(m), a);
97   }
98 
99   val.array_val = ret.array;
100   upb_Message_SetFieldByDef(msg, f, val, a);
101 
102   return ret;
103 }
104 
upb_Message_SetFieldByDef(upb_Message * msg,const upb_FieldDef * f,upb_MessageValue val,upb_Arena * a)105 bool upb_Message_SetFieldByDef(upb_Message* msg, const upb_FieldDef* f,
106                                upb_MessageValue val, upb_Arena* a) {
107   UPB_ASSERT(!upb_Message_IsFrozen(msg));
108   const upb_MiniTableField* m_f = upb_FieldDef_MiniTable(f);
109 
110   if (upb_MiniTableField_IsExtension(m_f)) {
111     return upb_Message_SetExtension(msg, (const upb_MiniTableExtension*)m_f,
112                                     &val, a);
113   } else {
114     upb_Message_SetBaseField(msg, m_f, &val);
115     return true;
116   }
117 }
118 
upb_Message_ClearFieldByDef(upb_Message * msg,const upb_FieldDef * f)119 void upb_Message_ClearFieldByDef(upb_Message* msg, const upb_FieldDef* f) {
120   UPB_ASSERT(!upb_Message_IsFrozen(msg));
121   const upb_MiniTableField* m_f = upb_FieldDef_MiniTable(f);
122 
123   if (upb_MiniTableField_IsExtension(m_f)) {
124     upb_Message_ClearExtension(msg, (const upb_MiniTableExtension*)m_f);
125   } else {
126     upb_Message_ClearBaseField(msg, m_f);
127   }
128 }
129 
upb_Message_ClearByDef(upb_Message * msg,const upb_MessageDef * m)130 void upb_Message_ClearByDef(upb_Message* msg, const upb_MessageDef* m) {
131   UPB_ASSERT(!upb_Message_IsFrozen(msg));
132   upb_Message_Clear(msg, upb_MessageDef_MiniTable(m));
133 }
134 
upb_Message_Next(const upb_Message * msg,const upb_MessageDef * m,const upb_DefPool * ext_pool,const upb_FieldDef ** out_f,upb_MessageValue * out_val,size_t * iter)135 bool upb_Message_Next(const upb_Message* msg, const upb_MessageDef* m,
136                       const upb_DefPool* ext_pool, const upb_FieldDef** out_f,
137                       upb_MessageValue* out_val, size_t* iter) {
138   const upb_MiniTable* mt = upb_MessageDef_MiniTable(m);
139   size_t i = *iter;
140   size_t n = upb_MiniTable_FieldCount(mt);
141   upb_MessageValue zero = upb_MessageValue_Zero();
142   UPB_UNUSED(ext_pool);
143 
144   // Iterate over normal fields, returning the first one that is set.
145   while (++i < n) {
146     const upb_MiniTableField* field = upb_MiniTable_GetFieldByIndex(mt, i);
147     upb_MessageValue val = upb_Message_GetField(msg, field, zero);
148 
149     // Skip field if unset or empty.
150     if (upb_MiniTableField_HasPresence(field)) {
151       if (!upb_Message_HasBaseField(msg, field)) continue;
152     } else {
153       switch (UPB_PRIVATE(_upb_MiniTableField_Mode)(field)) {
154         case kUpb_FieldMode_Map:
155           if (!val.map_val || upb_Map_Size(val.map_val) == 0) continue;
156           break;
157         case kUpb_FieldMode_Array:
158           if (!val.array_val || upb_Array_Size(val.array_val) == 0) continue;
159           break;
160         case kUpb_FieldMode_Scalar:
161           if (UPB_PRIVATE(_upb_MiniTableField_DataIsZero)(field, &val))
162             continue;
163           break;
164       }
165     }
166 
167     *out_val = val;
168     *out_f =
169         upb_MessageDef_FindFieldByNumber(m, upb_MiniTableField_Number(field));
170     *iter = i;
171     return true;
172   }
173 
174   if (ext_pool) {
175     // Return any extensions that are set.
176     size_t count;
177     const upb_Extension* ext = UPB_PRIVATE(_upb_Message_Getexts)(msg, &count);
178     if (i - n < count) {
179       ext += count - 1 - (i - n);
180       memcpy(out_val, &ext->data, sizeof(*out_val));
181       *out_f = upb_DefPool_FindExtensionByMiniTable(ext_pool, ext->ext);
182       *iter = i;
183       return true;
184     }
185   }
186 
187   *iter = i;
188   return false;
189 }
190 
_upb_Message_DiscardUnknown(upb_Message * msg,const upb_MessageDef * m,int depth)191 bool _upb_Message_DiscardUnknown(upb_Message* msg, const upb_MessageDef* m,
192                                  int depth) {
193   UPB_ASSERT(!upb_Message_IsFrozen(msg));
194   size_t iter = kUpb_Message_Begin;
195   const upb_FieldDef* f;
196   upb_MessageValue val;
197   bool ret = true;
198 
199   if (--depth == 0) return false;
200 
201   _upb_Message_DiscardUnknown_shallow(msg);
202 
203   while (upb_Message_Next(msg, m, NULL /*ext_pool*/, &f, &val, &iter)) {
204     const upb_MessageDef* subm = upb_FieldDef_MessageSubDef(f);
205     if (!subm) continue;
206     if (upb_FieldDef_IsMap(f)) {
207       const upb_FieldDef* val_f = upb_MessageDef_FindFieldByNumber(subm, 2);
208       const upb_MessageDef* val_m = upb_FieldDef_MessageSubDef(val_f);
209       upb_Map* map = (upb_Map*)val.map_val;
210       size_t iter = kUpb_Map_Begin;
211 
212       if (!val_m) continue;
213 
214       upb_MessageValue map_key, map_val;
215       while (upb_Map_Next(map, &map_key, &map_val, &iter)) {
216         if (!_upb_Message_DiscardUnknown((upb_Message*)map_val.msg_val, val_m,
217                                          depth)) {
218           ret = false;
219         }
220       }
221     } else if (upb_FieldDef_IsRepeated(f)) {
222       const upb_Array* arr = val.array_val;
223       size_t i, n = upb_Array_Size(arr);
224       for (i = 0; i < n; i++) {
225         upb_MessageValue elem = upb_Array_Get(arr, i);
226         if (!_upb_Message_DiscardUnknown((upb_Message*)elem.msg_val, subm,
227                                          depth)) {
228           ret = false;
229         }
230       }
231     } else {
232       if (!_upb_Message_DiscardUnknown((upb_Message*)val.msg_val, subm,
233                                        depth)) {
234         ret = false;
235       }
236     }
237   }
238 
239   return ret;
240 }
241 
upb_Message_DiscardUnknown(upb_Message * msg,const upb_MessageDef * m,int maxdepth)242 bool upb_Message_DiscardUnknown(upb_Message* msg, const upb_MessageDef* m,
243                                 int maxdepth) {
244   return _upb_Message_DiscardUnknown(msg, m, maxdepth);
245 }
246