msg.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. #include "upb/msg.h"
  2. #include "upb/table.int.h"
  3. #include "upb/port_def.inc"
  4. #define VOIDPTR_AT(msg, ofs) (void*)((char*)msg + (int)ofs)
  5. /** upb_msg *******************************************************************/
  6. static char _upb_fieldtype_to_sizelg2[12] = {
  7. 0,
  8. 0, /* UPB_TYPE_BOOL */
  9. 2, /* UPB_TYPE_FLOAT */
  10. 2, /* UPB_TYPE_INT32 */
  11. 2, /* UPB_TYPE_UINT32 */
  12. 2, /* UPB_TYPE_ENUM */
  13. UPB_SIZE(2, 3), /* UPB_TYPE_MESSAGE */
  14. 3, /* UPB_TYPE_DOUBLE */
  15. 3, /* UPB_TYPE_INT64 */
  16. 3, /* UPB_TYPE_UINT64 */
  17. UPB_SIZE(3, 4), /* UPB_TYPE_STRING */
  18. UPB_SIZE(3, 4), /* UPB_TYPE_BYTES */
  19. };
  20. static uintptr_t tag_arrptr(void* ptr, int elem_size_lg2) {
  21. UPB_ASSERT(elem_size_lg2 <= 4);
  22. return (uintptr_t)ptr | elem_size_lg2;
  23. }
  24. static int upb_msg_internalsize(const upb_msglayout *l) {
  25. return sizeof(upb_msg_internal) - l->extendable * sizeof(void *);
  26. }
  27. static size_t upb_msg_sizeof(const upb_msglayout *l) {
  28. return l->size + upb_msg_internalsize(l);
  29. }
  30. static upb_msg_internal *upb_msg_getinternal(upb_msg *msg) {
  31. return VOIDPTR_AT(msg, -sizeof(upb_msg_internal));
  32. }
  33. static const upb_msg_internal *upb_msg_getinternal_const(const upb_msg *msg) {
  34. return VOIDPTR_AT(msg, -sizeof(upb_msg_internal));
  35. }
  36. static upb_msg_internal_withext *upb_msg_getinternalwithext(
  37. upb_msg *msg, const upb_msglayout *l) {
  38. UPB_ASSERT(l->extendable);
  39. return VOIDPTR_AT(msg, -sizeof(upb_msg_internal_withext));
  40. }
  41. upb_msg *_upb_msg_new(const upb_msglayout *l, upb_arena *a) {
  42. upb_alloc *alloc = upb_arena_alloc(a);
  43. void *mem = upb_malloc(alloc, upb_msg_sizeof(l));
  44. upb_msg_internal *in;
  45. upb_msg *msg;
  46. if (!mem) {
  47. return NULL;
  48. }
  49. msg = VOIDPTR_AT(mem, upb_msg_internalsize(l));
  50. /* Initialize normal members. */
  51. memset(msg, 0, l->size);
  52. /* Initialize internal members. */
  53. in = upb_msg_getinternal(msg);
  54. in->unknown = NULL;
  55. in->unknown_len = 0;
  56. in->unknown_size = 0;
  57. if (l->extendable) {
  58. upb_msg_getinternalwithext(msg, l)->extdict = NULL;
  59. }
  60. return msg;
  61. }
  62. void upb_msg_addunknown(upb_msg *msg, const char *data, size_t len,
  63. upb_arena *arena) {
  64. upb_msg_internal *in = upb_msg_getinternal(msg);
  65. if (len > in->unknown_size - in->unknown_len) {
  66. upb_alloc *alloc = upb_arena_alloc(arena);
  67. size_t need = in->unknown_size + len;
  68. size_t newsize = UPB_MAX(in->unknown_size * 2, need);
  69. in->unknown = upb_realloc(alloc, in->unknown, in->unknown_size, newsize);
  70. in->unknown_size = newsize;
  71. }
  72. memcpy(in->unknown + in->unknown_len, data, len);
  73. in->unknown_len += len;
  74. }
  75. const char *upb_msg_getunknown(const upb_msg *msg, size_t *len) {
  76. const upb_msg_internal *in = upb_msg_getinternal_const(msg);
  77. *len = in->unknown_len;
  78. return in->unknown;
  79. }
  80. /** upb_array *****************************************************************/
  81. upb_array *_upb_array_new(upb_arena *a, upb_fieldtype_t type) {
  82. upb_array *arr = upb_arena_malloc(a, sizeof(upb_array));
  83. if (!arr) {
  84. return NULL;
  85. }
  86. arr->data = tag_arrptr(NULL, _upb_fieldtype_to_sizelg2[type]);
  87. arr->len = 0;
  88. arr->size = 0;
  89. return arr;
  90. }
  91. bool _upb_array_realloc(upb_array *arr, size_t min_size, upb_arena *arena) {
  92. size_t new_size = UPB_MAX(arr->size, 4);
  93. int elem_size_lg2 = arr->data & 7;
  94. size_t old_bytes = arr->size << elem_size_lg2;
  95. size_t new_bytes;
  96. void* ptr = _upb_array_ptr(arr);
  97. /* Log2 ceiling of size. */
  98. while (new_size < min_size) new_size *= 2;
  99. new_bytes = new_size << elem_size_lg2;
  100. ptr = upb_arena_realloc(arena, ptr, old_bytes, new_bytes);
  101. if (!ptr) {
  102. return false;
  103. }
  104. arr->data = tag_arrptr(ptr, elem_size_lg2);
  105. arr->size = new_size;
  106. return true;
  107. }
  108. static upb_array *getorcreate_array(upb_array **arr_ptr, upb_fieldtype_t type,
  109. upb_arena *arena) {
  110. upb_array *arr = *arr_ptr;
  111. if (!arr) {
  112. arr = _upb_array_new(arena, type);
  113. if (!arr) return NULL;
  114. *arr_ptr = arr;
  115. }
  116. return arr;
  117. }
  118. static bool resize_array(upb_array *arr, size_t size, upb_arena *arena) {
  119. if (size > arr->size && !_upb_array_realloc(arr, size, arena)) {
  120. return false;
  121. }
  122. arr->len = size;
  123. return true;
  124. }
  125. void *_upb_array_resize_fallback(upb_array **arr_ptr, size_t size,
  126. upb_fieldtype_t type, upb_arena *arena) {
  127. upb_array *arr = getorcreate_array(arr_ptr, type, arena);
  128. return arr && resize_array(arr, size, arena) ? _upb_array_ptr(arr) : NULL;
  129. }
  130. bool _upb_array_append_fallback(upb_array **arr_ptr, const void *value,
  131. upb_fieldtype_t type, upb_arena *arena) {
  132. upb_array *arr = getorcreate_array(arr_ptr, type, arena);
  133. size_t elem = arr->len;
  134. int lg2 = _upb_fieldtype_to_sizelg2[type];
  135. char *data;
  136. if (!arr || !resize_array(arr, elem + 1, arena)) return false;
  137. data = _upb_array_ptr(arr);
  138. memcpy(data + (elem << lg2), value, 1 << lg2);
  139. return true;
  140. }
  141. /** upb_map *******************************************************************/
  142. upb_map *_upb_map_new(upb_arena *a, size_t key_size, size_t value_size) {
  143. upb_map *map = upb_arena_malloc(a, sizeof(upb_map));
  144. if (!map) {
  145. return NULL;
  146. }
  147. upb_strtable_init2(&map->table, UPB_CTYPE_INT32, upb_arena_alloc(a));
  148. map->key_size = key_size;
  149. map->val_size = value_size;
  150. return map;
  151. }
  152. #undef VOIDPTR_AT