Built motion from commit 6a09e18b.|2.6.11
[motion2.git] / legacy-libs / grpc / deps / grpc / third_party / upb / upb / legacy_msg_reflection.c
1
2 #include "upb/legacy_msg_reflection.h"
3
4 #include <string.h>
5 #include "upb/table.int.h"
6 #include "upb/msg.h"
7
8 #include "upb/port_def.inc"
9
10 bool upb_fieldtype_mapkeyok(upb_fieldtype_t type) {
11   return type == UPB_TYPE_BOOL || type == UPB_TYPE_INT32 ||
12          type == UPB_TYPE_UINT32 || type == UPB_TYPE_INT64 ||
13          type == UPB_TYPE_UINT64 || type == UPB_TYPE_STRING;
14 }
15
16 #define PTR_AT(msg, ofs, type) (type*)((char*)msg + ofs)
17 #define VOIDPTR_AT(msg, ofs) PTR_AT(msg, ofs, void)
18 #define ENCODE_MAX_NESTING 64
19 #define CHECK_TRUE(x) if (!(x)) { return false; }
20
21 /** upb_msgval ****************************************************************/
22
23 /* These functions will generate real memcpy() calls on ARM sadly, because
24  * the compiler assumes they might not be aligned. */
25
26 static upb_msgval upb_msgval_read(const void *p, size_t ofs,
27                                   uint8_t size) {
28   upb_msgval val;
29   p = (char*)p + ofs;
30   memcpy(&val, p, size);
31   return val;
32 }
33
34 static void upb_msgval_write(void *p, size_t ofs, upb_msgval val,
35                              uint8_t size) {
36   p = (char*)p + ofs;
37   memcpy(p, &val, size);
38 }
39
40 static size_t upb_msgval_sizeof(upb_fieldtype_t type) {
41   switch (type) {
42     case UPB_TYPE_DOUBLE:
43     case UPB_TYPE_INT64:
44     case UPB_TYPE_UINT64:
45       return 8;
46     case UPB_TYPE_ENUM:
47     case UPB_TYPE_INT32:
48     case UPB_TYPE_UINT32:
49     case UPB_TYPE_FLOAT:
50       return 4;
51     case UPB_TYPE_BOOL:
52       return 1;
53     case UPB_TYPE_MESSAGE:
54       return sizeof(void*);
55     case UPB_TYPE_BYTES:
56     case UPB_TYPE_STRING:
57       return sizeof(upb_strview);
58   }
59   UPB_UNREACHABLE();
60 }
61
62 static uint8_t upb_msg_fieldsize(const upb_msglayout_field *field) {
63   if (field->label == UPB_LABEL_REPEATED) {
64     return sizeof(void*);
65   } else {
66     return upb_msgval_sizeof(upb_desctype_to_fieldtype[field->descriptortype]);
67   }
68 }
69
70 /* TODO(haberman): this is broken right now because upb_msgval can contain
71  * a char* / size_t pair, which is too big for a upb_value.  To fix this
72  * we'll probably need to dynamically allocate a upb_msgval and store a
73  * pointer to that in the tables for extensions/maps. */
74 static upb_value upb_toval(upb_msgval val) {
75   upb_value ret;
76   UPB_UNUSED(val);
77   memset(&ret, 0, sizeof(upb_value));  /* XXX */
78   return ret;
79 }
80
81 static upb_msgval upb_msgval_fromval(upb_value val) {
82   upb_msgval ret;
83   UPB_UNUSED(val);
84   memset(&ret, 0, sizeof(upb_msgval));  /* XXX */
85   return ret;
86 }
87
88 static upb_ctype_t upb_fieldtotabtype(upb_fieldtype_t type) {
89   switch (type) {
90     case UPB_TYPE_FLOAT: return UPB_CTYPE_FLOAT;
91     case UPB_TYPE_DOUBLE: return UPB_CTYPE_DOUBLE;
92     case UPB_TYPE_BOOL: return UPB_CTYPE_BOOL;
93     case UPB_TYPE_BYTES:
94     case UPB_TYPE_MESSAGE:
95     case UPB_TYPE_STRING: return UPB_CTYPE_CONSTPTR;
96     case UPB_TYPE_ENUM:
97     case UPB_TYPE_INT32: return UPB_CTYPE_INT32;
98     case UPB_TYPE_UINT32: return UPB_CTYPE_UINT32;
99     case UPB_TYPE_INT64: return UPB_CTYPE_INT64;
100     case UPB_TYPE_UINT64: return UPB_CTYPE_UINT64;
101     default: UPB_ASSERT(false); return 0;
102   }
103 }
104
105
106 /** upb_msg *******************************************************************/
107
108 /* If we always read/write as a consistent type to each address, this shouldn't
109  * violate aliasing.
110  */
111 #define DEREF(msg, ofs, type) *PTR_AT(msg, ofs, type)
112
113 static const upb_msglayout_field *upb_msg_checkfield(int field_index,
114                                                      const upb_msglayout *l) {
115   UPB_ASSERT(field_index >= 0 && field_index < l->field_count);
116   return &l->fields[field_index];
117 }
118
119 static bool upb_msg_inoneof(const upb_msglayout_field *field) {
120   return field->presence < 0;
121 }
122
123 static uint32_t *upb_msg_oneofcase(const upb_msg *msg, int field_index,
124                                    const upb_msglayout *l) {
125   const upb_msglayout_field *field = upb_msg_checkfield(field_index, l);
126   UPB_ASSERT(upb_msg_inoneof(field));
127   return PTR_AT(msg, ~field->presence, uint32_t);
128 }
129
130 bool upb_msg_has(const upb_msg *msg,
131                  int field_index,
132                  const upb_msglayout *l) {
133   const upb_msglayout_field *field = upb_msg_checkfield(field_index, l);
134
135   UPB_ASSERT(field->presence);
136
137   if (upb_msg_inoneof(field)) {
138     /* Oneofs are set when the oneof number is set to this field. */
139     return *upb_msg_oneofcase(msg, field_index, l) == field->number;
140   } else {
141     /* Other fields are set when their hasbit is set. */
142     uint32_t hasbit = field->presence;
143     return DEREF(msg, hasbit / 8, char) | (1 << (hasbit % 8));
144   }
145 }
146
147 upb_msgval upb_msg_get(const upb_msg *msg, int field_index,
148                        const upb_msglayout *l) {
149   const upb_msglayout_field *field = upb_msg_checkfield(field_index, l);
150   int size = upb_msg_fieldsize(field);
151   return upb_msgval_read(msg, field->offset, size);
152 }
153
154 void upb_msg_set(upb_msg *msg, int field_index, upb_msgval val,
155                  const upb_msglayout *l) {
156   const upb_msglayout_field *field = upb_msg_checkfield(field_index, l);
157   int size = upb_msg_fieldsize(field);
158   upb_msgval_write(msg, field->offset, val, size);
159 }
160
161
162 /** upb_array *****************************************************************/
163
164 #define DEREF_ARR(arr, i, type) ((type*)arr->data)[i]
165
166 size_t upb_array_size(const upb_array *arr) {
167   return arr->len;
168 }
169
170 upb_msgval upb_array_get(const upb_array *arr, upb_fieldtype_t type, size_t i) {
171   size_t element_size = upb_msgval_sizeof(type);
172   UPB_ASSERT(i < arr->len);
173   return upb_msgval_read(arr->data, i * element_size, element_size);
174 }
175
176 bool upb_array_set(upb_array *arr, upb_fieldtype_t type, size_t i,
177                    upb_msgval val, upb_arena *arena) {
178   size_t element_size = upb_msgval_sizeof(type);
179   UPB_ASSERT(i <= arr->len);
180
181   if (i == arr->len) {
182     /* Extending the array. */
183
184     if (i == arr->size) {
185       /* Need to reallocate. */
186       size_t new_size = UPB_MAX(arr->size * 2, 8);
187       size_t new_bytes = new_size * element_size;
188       size_t old_bytes = arr->size * element_size;
189       upb_alloc *alloc = upb_arena_alloc(arena);
190       upb_msgval *new_data =
191           upb_realloc(alloc, arr->data, old_bytes, new_bytes);
192
193       if (!new_data) {
194         return false;
195       }
196
197       arr->data = new_data;
198       arr->size = new_size;
199     }
200
201     arr->len = i + 1;
202   }
203
204   upb_msgval_write(arr->data, i * element_size, val, element_size);
205   return true;
206 }
207
208 /** upb_map *******************************************************************/
209
210 struct upb_map {
211   upb_fieldtype_t key_type;
212   upb_fieldtype_t val_type;
213   /* We may want to optimize this to use inttable where possible, for greater
214    * efficiency and lower memory footprint. */
215   upb_strtable strtab;
216   upb_arena *arena;
217 };
218
219 static void upb_map_tokey(upb_fieldtype_t type, upb_msgval *key,
220                           const char **out_key, size_t *out_len) {
221   switch (type) {
222     case UPB_TYPE_STRING:
223       /* Point to string data of the input key. */
224       *out_key = key->str.data;
225       *out_len = key->str.size;
226       return;
227     case UPB_TYPE_BOOL:
228     case UPB_TYPE_INT32:
229     case UPB_TYPE_UINT32:
230     case UPB_TYPE_INT64:
231     case UPB_TYPE_UINT64:
232       /* Point to the key itself.  XXX: big-endian. */
233       *out_key = (const char*)key;
234       *out_len = upb_msgval_sizeof(type);
235       return;
236     case UPB_TYPE_BYTES:
237     case UPB_TYPE_DOUBLE:
238     case UPB_TYPE_ENUM:
239     case UPB_TYPE_FLOAT:
240     case UPB_TYPE_MESSAGE:
241       break;  /* Cannot be a map key. */
242   }
243   UPB_UNREACHABLE();
244 }
245
246 static upb_msgval upb_map_fromkey(upb_fieldtype_t type, const char *key,
247                                   size_t len) {
248   switch (type) {
249     case UPB_TYPE_STRING:
250       return upb_msgval_makestr(key, len);
251     case UPB_TYPE_BOOL:
252     case UPB_TYPE_INT32:
253     case UPB_TYPE_UINT32:
254     case UPB_TYPE_INT64:
255     case UPB_TYPE_UINT64:
256       return upb_msgval_read(key, 0, upb_msgval_sizeof(type));
257     case UPB_TYPE_BYTES:
258     case UPB_TYPE_DOUBLE:
259     case UPB_TYPE_ENUM:
260     case UPB_TYPE_FLOAT:
261     case UPB_TYPE_MESSAGE:
262       break;  /* Cannot be a map key. */
263   }
264   UPB_UNREACHABLE();
265 }
266
267 upb_map *upb_map_new(upb_fieldtype_t ktype, upb_fieldtype_t vtype,
268                      upb_arena *a) {
269   upb_ctype_t vtabtype = upb_fieldtotabtype(vtype);
270   upb_alloc *alloc = upb_arena_alloc(a);
271   upb_map *map = upb_malloc(alloc, sizeof(upb_map));
272
273   if (!map) {
274     return NULL;
275   }
276
277   UPB_ASSERT(upb_fieldtype_mapkeyok(ktype));
278   map->key_type = ktype;
279   map->val_type = vtype;
280   map->arena = a;
281
282   if (!upb_strtable_init2(&map->strtab, vtabtype, alloc)) {
283     return NULL;
284   }
285
286   return map;
287 }
288
289 size_t upb_map_size(const upb_map *map) {
290   return upb_strtable_count(&map->strtab);
291 }
292
293 upb_fieldtype_t upb_map_keytype(const upb_map *map) {
294   return map->key_type;
295 }
296
297 upb_fieldtype_t upb_map_valuetype(const upb_map *map) {
298   return map->val_type;
299 }
300
301 bool upb_map_get(const upb_map *map, upb_msgval key, upb_msgval *val) {
302   upb_value tabval;
303   const char *key_str;
304   size_t key_len;
305   bool ret;
306
307   upb_map_tokey(map->key_type, &key, &key_str, &key_len);
308   ret = upb_strtable_lookup2(&map->strtab, key_str, key_len, &tabval);
309   if (ret) {
310     memcpy(val, &tabval, sizeof(tabval));
311   }
312
313   return ret;
314 }
315
316 bool upb_map_set(upb_map *map, upb_msgval key, upb_msgval val,
317                  upb_msgval *removed) {
318   const char *key_str;
319   size_t key_len;
320   upb_value tabval = upb_toval(val);
321   upb_value removedtabval;
322   upb_alloc *a = upb_arena_alloc(map->arena);
323
324   upb_map_tokey(map->key_type, &key, &key_str, &key_len);
325
326   /* TODO(haberman): add overwrite operation to minimize number of lookups. */
327   if (upb_strtable_lookup2(&map->strtab, key_str, key_len, NULL)) {
328     upb_strtable_remove3(&map->strtab, key_str, key_len, &removedtabval, a);
329     memcpy(&removed, &removedtabval, sizeof(removed));
330   }
331
332   return upb_strtable_insert3(&map->strtab, key_str, key_len, tabval, a);
333 }
334
335 bool upb_map_del(upb_map *map, upb_msgval key) {
336   const char *key_str;
337   size_t key_len;
338   upb_alloc *a = upb_arena_alloc(map->arena);
339
340   upb_map_tokey(map->key_type, &key, &key_str, &key_len);
341   return upb_strtable_remove3(&map->strtab, key_str, key_len, NULL, a);
342 }
343
344
345 /** upb_mapiter ***************************************************************/
346
347 struct upb_mapiter {
348   upb_strtable_iter iter;
349   upb_fieldtype_t key_type;
350 };
351
352 size_t upb_mapiter_sizeof(void) {
353   return sizeof(upb_mapiter);
354 }
355
356 void upb_mapiter_begin(upb_mapiter *i, const upb_map *map) {
357   upb_strtable_begin(&i->iter, &map->strtab);
358   i->key_type = map->key_type;
359 }
360
361 upb_mapiter *upb_mapiter_new(const upb_map *t, upb_alloc *a) {
362   upb_mapiter *ret = upb_malloc(a, upb_mapiter_sizeof());
363
364   if (!ret) {
365     return NULL;
366   }
367
368   upb_mapiter_begin(ret, t);
369   return ret;
370 }
371
372 void upb_mapiter_free(upb_mapiter *i, upb_alloc *a) {
373   upb_free(a, i);
374 }
375
376 void upb_mapiter_next(upb_mapiter *i) {
377   upb_strtable_next(&i->iter);
378 }
379
380 bool upb_mapiter_done(const upb_mapiter *i) {
381   return upb_strtable_done(&i->iter);
382 }
383
384 upb_msgval upb_mapiter_key(const upb_mapiter *i) {
385   return upb_map_fromkey(i->key_type, upb_strtable_iter_key(&i->iter),
386                          upb_strtable_iter_keylength(&i->iter));
387 }
388
389 upb_msgval upb_mapiter_value(const upb_mapiter *i) {
390   return upb_msgval_fromval(upb_strtable_iter_value(&i->iter));
391 }
392
393 void upb_mapiter_setdone(upb_mapiter *i) {
394   upb_strtable_iter_setdone(&i->iter);
395 }
396
397 bool upb_mapiter_isequal(const upb_mapiter *i1, const upb_mapiter *i2) {
398   return upb_strtable_iter_isequal(&i1->iter, &i2->iter);
399 }