reflection.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. #include "upb/reflection.h"
  2. #include <string.h>
  3. #include "upb/table.int.h"
  4. #include "upb/msg.h"
  5. #include "upb/port_def.inc"
  6. static char field_size[] = {
  7. 0,/* 0 */
  8. 8, /* UPB_DESCRIPTOR_TYPE_DOUBLE */
  9. 4, /* UPB_DESCRIPTOR_TYPE_FLOAT */
  10. 8, /* UPB_DESCRIPTOR_TYPE_INT64 */
  11. 8, /* UPB_DESCRIPTOR_TYPE_UINT64 */
  12. 4, /* UPB_DESCRIPTOR_TYPE_INT32 */
  13. 8, /* UPB_DESCRIPTOR_TYPE_FIXED64 */
  14. 4, /* UPB_DESCRIPTOR_TYPE_FIXED32 */
  15. 1, /* UPB_DESCRIPTOR_TYPE_BOOL */
  16. sizeof(upb_strview), /* UPB_DESCRIPTOR_TYPE_STRING */
  17. sizeof(void*), /* UPB_DESCRIPTOR_TYPE_GROUP */
  18. sizeof(void*), /* UPB_DESCRIPTOR_TYPE_MESSAGE */
  19. sizeof(upb_strview), /* UPB_DESCRIPTOR_TYPE_BYTES */
  20. 4, /* UPB_DESCRIPTOR_TYPE_UINT32 */
  21. 4, /* UPB_DESCRIPTOR_TYPE_ENUM */
  22. 4, /* UPB_DESCRIPTOR_TYPE_SFIXED32 */
  23. 8, /* UPB_DESCRIPTOR_TYPE_SFIXED64 */
  24. 4, /* UPB_DESCRIPTOR_TYPE_SINT32 */
  25. 8, /* UPB_DESCRIPTOR_TYPE_SINT64 */
  26. };
  27. /* Strings/bytes are special-cased in maps. */
  28. static char _upb_fieldtype_to_mapsize[12] = {
  29. 0,
  30. 1, /* UPB_TYPE_BOOL */
  31. 4, /* UPB_TYPE_FLOAT */
  32. 4, /* UPB_TYPE_INT32 */
  33. 4, /* UPB_TYPE_UINT32 */
  34. 4, /* UPB_TYPE_ENUM */
  35. sizeof(void*), /* UPB_TYPE_MESSAGE */
  36. 8, /* UPB_TYPE_DOUBLE */
  37. 8, /* UPB_TYPE_INT64 */
  38. 8, /* UPB_TYPE_UINT64 */
  39. 0, /* UPB_TYPE_STRING */
  40. 0, /* UPB_TYPE_BYTES */
  41. };
  42. /** upb_msg *******************************************************************/
  43. /* If we always read/write as a consistent type to each address, this shouldn't
  44. * violate aliasing.
  45. */
  46. #define PTR_AT(msg, ofs, type) (type*)((char*)msg + ofs)
  47. upb_msg *upb_msg_new(const upb_msgdef *m, upb_arena *a) {
  48. return _upb_msg_new(upb_msgdef_layout(m), a);
  49. }
  50. static bool in_oneof(const upb_msglayout_field *field) {
  51. return field->presence < 0;
  52. }
  53. static uint32_t *oneofcase(const upb_msg *msg,
  54. const upb_msglayout_field *field) {
  55. UPB_ASSERT(in_oneof(field));
  56. return PTR_AT(msg, ~field->presence, uint32_t);
  57. }
  58. static upb_msgval _upb_msg_getraw(const upb_msg *msg, const upb_fielddef *f) {
  59. const upb_msglayout_field *field = upb_fielddef_layout(f);
  60. const char *mem = PTR_AT(msg, field->offset, char);
  61. upb_msgval val = {0};
  62. int size = upb_fielddef_isseq(f) ? sizeof(void *)
  63. : field_size[field->descriptortype];
  64. memcpy(&val, mem, size);
  65. return val;
  66. }
  67. bool upb_msg_has(const upb_msg *msg, const upb_fielddef *f) {
  68. const upb_msglayout_field *field = upb_fielddef_layout(f);
  69. if (in_oneof(field)) {
  70. return *oneofcase(msg, field) == field->number;
  71. } else if (field->presence > 0) {
  72. uint32_t hasbit = field->presence;
  73. return *PTR_AT(msg, hasbit / 8, char) & (1 << (hasbit % 8));
  74. } else {
  75. UPB_ASSERT(field->descriptortype == UPB_DESCRIPTOR_TYPE_MESSAGE ||
  76. field->descriptortype == UPB_DESCRIPTOR_TYPE_GROUP);
  77. return _upb_msg_getraw(msg, f).msg_val != NULL;
  78. }
  79. }
  80. upb_msgval upb_msg_get(const upb_msg *msg, const upb_fielddef *f) {
  81. if (!upb_fielddef_haspresence(f) || upb_msg_has(msg, f)) {
  82. return _upb_msg_getraw(msg, f);
  83. } else {
  84. /* TODO(haberman): change upb_fielddef to not require this switch(). */
  85. upb_msgval val = {0};
  86. switch (upb_fielddef_type(f)) {
  87. case UPB_TYPE_INT32:
  88. case UPB_TYPE_ENUM:
  89. val.int32_val = upb_fielddef_defaultint32(f);
  90. break;
  91. case UPB_TYPE_INT64:
  92. val.int64_val = upb_fielddef_defaultint64(f);
  93. break;
  94. case UPB_TYPE_UINT32:
  95. val.uint32_val = upb_fielddef_defaultuint32(f);
  96. break;
  97. case UPB_TYPE_UINT64:
  98. val.uint64_val = upb_fielddef_defaultuint64(f);
  99. break;
  100. case UPB_TYPE_FLOAT:
  101. val.float_val = upb_fielddef_defaultfloat(f);
  102. break;
  103. case UPB_TYPE_DOUBLE:
  104. val.double_val = upb_fielddef_defaultdouble(f);
  105. break;
  106. case UPB_TYPE_BOOL:
  107. val.double_val = upb_fielddef_defaultbool(f);
  108. break;
  109. case UPB_TYPE_STRING:
  110. case UPB_TYPE_BYTES:
  111. val.str_val.data = upb_fielddef_defaultstr(f, &val.str_val.size);
  112. break;
  113. case UPB_TYPE_MESSAGE:
  114. val.msg_val = NULL;
  115. break;
  116. }
  117. return val;
  118. }
  119. }
  120. upb_mutmsgval upb_msg_mutable(upb_msg *msg, const upb_fielddef *f,
  121. upb_arena *a) {
  122. const upb_msglayout_field *field = upb_fielddef_layout(f);
  123. upb_mutmsgval ret;
  124. char *mem = PTR_AT(msg, field->offset, char);
  125. memcpy(&ret, mem, sizeof(void*));
  126. if (a && !ret.msg) {
  127. if (upb_fielddef_ismap(f)) {
  128. const upb_msgdef *entry = upb_fielddef_msgsubdef(f);
  129. const upb_fielddef *key = upb_msgdef_itof(entry, UPB_MAPENTRY_KEY);
  130. const upb_fielddef *value = upb_msgdef_itof(entry, UPB_MAPENTRY_VALUE);
  131. ret.map = upb_map_new(a, upb_fielddef_type(key), upb_fielddef_type(value));
  132. } else if (upb_fielddef_isseq(f)) {
  133. ret.array = upb_array_new(a, upb_fielddef_type(f));
  134. } else {
  135. UPB_ASSERT(upb_fielddef_issubmsg(f));
  136. ret.msg = upb_msg_new(upb_fielddef_msgsubdef(f), a);
  137. }
  138. memcpy(mem, &ret, sizeof(void*));
  139. }
  140. return ret;
  141. }
  142. void upb_msg_set(upb_msg *msg, const upb_fielddef *f, upb_msgval val,
  143. upb_arena *a) {
  144. const upb_msglayout_field *field = upb_fielddef_layout(f);
  145. char *mem = PTR_AT(msg, field->offset, char);
  146. int size = upb_fielddef_isseq(f) ? sizeof(void *)
  147. : field_size[field->descriptortype];
  148. memcpy(mem, &val, size);
  149. if (in_oneof(field)) {
  150. *oneofcase(msg, field) = field->number;
  151. }
  152. }
  153. bool upb_msg_next(const upb_msg *msg, const upb_msgdef *m,
  154. const upb_symtab *ext_pool, const upb_fielddef **out_f,
  155. upb_msgval *out_val, size_t *iter) {
  156. int i = *iter;
  157. const upb_msgval zero = {0};
  158. const upb_fielddef *f;
  159. while ((f = _upb_msgdef_field(m, ++i)) != NULL) {
  160. upb_msgval val = _upb_msg_getraw(msg, f);
  161. /* Skip field if unset or empty. */
  162. if (upb_fielddef_haspresence(f)) {
  163. if (!upb_msg_has(msg, f)) continue;
  164. } else {
  165. upb_msgval test = val;
  166. if (upb_fielddef_isstring(f) && !upb_fielddef_isseq(f)) {
  167. /* Clear string pointer, only size matters (ptr could be non-NULL). */
  168. test.str_val.data = NULL;
  169. }
  170. /* Continue if NULL or 0. */
  171. if (memcmp(&test, &zero, sizeof(test)) == 0) continue;
  172. }
  173. *out_val = val;
  174. *out_f = f;
  175. *iter = i;
  176. return true;
  177. }
  178. *iter = i;
  179. return false;
  180. }
  181. /** upb_array *****************************************************************/
  182. upb_array *upb_array_new(upb_arena *a, upb_fieldtype_t type) {
  183. return _upb_array_new(a, type);
  184. }
  185. size_t upb_array_size(const upb_array *arr) {
  186. return arr->len;
  187. }
  188. upb_msgval upb_array_get(const upb_array *arr, size_t i) {
  189. upb_msgval ret;
  190. const char* data = _upb_array_constptr(arr);
  191. int lg2 = arr->data & 7;
  192. UPB_ASSERT(i < arr->len);
  193. memcpy(&ret, data + (i << lg2), 1 << lg2);
  194. return ret;
  195. }
  196. void upb_array_set(upb_array *arr, size_t i, upb_msgval val) {
  197. char* data = _upb_array_ptr(arr);
  198. int lg2 = arr->data & 7;
  199. UPB_ASSERT(i < arr->len);
  200. memcpy(data + (i << lg2), &val, 1 << lg2);
  201. }
  202. bool upb_array_append(upb_array *arr, upb_msgval val, upb_arena *arena) {
  203. if (!_upb_array_realloc(arr, arr->len + 1, arena)) {
  204. return false;
  205. }
  206. arr->len++;
  207. upb_array_set(arr, arr->len - 1, val);
  208. return true;
  209. }
  210. /* Resizes the array to the given size, reallocating if necessary, and returns a
  211. * pointer to the new array elements. */
  212. bool upb_array_resize(upb_array *arr, size_t size, upb_arena *arena) {
  213. return _upb_array_realloc(arr, size, arena);
  214. }
  215. /** upb_map *******************************************************************/
  216. upb_map *upb_map_new(upb_arena *a, upb_fieldtype_t key_type,
  217. upb_fieldtype_t value_type) {
  218. return _upb_map_new(a, _upb_fieldtype_to_mapsize[key_type],
  219. _upb_fieldtype_to_mapsize[value_type]);
  220. }
  221. size_t upb_map_size(const upb_map *map) {
  222. return _upb_map_size(map);
  223. }
  224. bool upb_map_get(const upb_map *map, upb_msgval key, upb_msgval *val) {
  225. return _upb_map_get(map, &key, map->key_size, val, map->val_size);
  226. }
  227. bool upb_map_set(upb_map *map, upb_msgval key, upb_msgval val,
  228. upb_arena *arena) {
  229. return _upb_map_set(map, &key, map->key_size, &val, map->val_size, arena);
  230. }
  231. bool upb_map_delete(upb_map *map, upb_msgval key) {
  232. return _upb_map_delete(map, &key, map->key_size);
  233. }
  234. bool upb_mapiter_next(const upb_map *map, size_t *iter) {
  235. return _upb_map_next(map, iter);
  236. }
  237. /* Returns the key and value for this entry of the map. */
  238. upb_msgval upb_mapiter_key(const upb_map *map, size_t iter) {
  239. upb_strtable_iter i;
  240. upb_msgval ret;
  241. i.t = &map->table;
  242. i.index = iter;
  243. _upb_map_fromkey(upb_strtable_iter_key(&i), &ret, map->key_size);
  244. return ret;
  245. }
  246. upb_msgval upb_mapiter_value(const upb_map *map, size_t iter) {
  247. upb_strtable_iter i;
  248. upb_msgval ret;
  249. i.t = &map->table;
  250. i.index = iter;
  251. _upb_map_fromvalue(upb_strtable_iter_value(&i), &ret, map->val_size);
  252. return ret;
  253. }
  254. /* void upb_mapiter_setvalue(upb_map *map, size_t iter, upb_msgval value); */