encode.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571
  1. /*
  2. * Copyright (c) 2009-2021, 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" AND
  17. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  18. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19. * DISCLAIMED. IN NO EVENT SHALL Google LLC BE LIABLE FOR ANY
  20. * DIRECT, 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. /* We encode backwards, to avoid pre-computing lengths (one-pass encode). */
  28. #include "upb/encode.h"
  29. #include <setjmp.h>
  30. #include <string.h>
  31. #include "upb/msg_internal.h"
  32. #include "upb/upb.h"
  33. /* Must be last. */
  34. #include "upb/port_def.inc"
  35. #define UPB_PB_VARINT_MAX_LEN 10
  36. UPB_NOINLINE
  37. static size_t encode_varint64(uint64_t val, char *buf) {
  38. size_t i = 0;
  39. do {
  40. uint8_t byte = val & 0x7fU;
  41. val >>= 7;
  42. if (val) byte |= 0x80U;
  43. buf[i++] = byte;
  44. } while (val);
  45. return i;
  46. }
  47. static uint32_t encode_zz32(int32_t n) { return ((uint32_t)n << 1) ^ (n >> 31); }
  48. static uint64_t encode_zz64(int64_t n) { return ((uint64_t)n << 1) ^ (n >> 63); }
  49. typedef struct {
  50. jmp_buf err;
  51. upb_alloc *alloc;
  52. char *buf, *ptr, *limit;
  53. int options;
  54. int depth;
  55. _upb_mapsorter sorter;
  56. } upb_encstate;
  57. static size_t upb_roundup_pow2(size_t bytes) {
  58. size_t ret = 128;
  59. while (ret < bytes) {
  60. ret *= 2;
  61. }
  62. return ret;
  63. }
  64. UPB_NORETURN static void encode_err(upb_encstate *e) {
  65. UPB_LONGJMP(e->err, 1);
  66. }
  67. UPB_NOINLINE
  68. static void encode_growbuffer(upb_encstate *e, size_t bytes) {
  69. size_t old_size = e->limit - e->buf;
  70. size_t new_size = upb_roundup_pow2(bytes + (e->limit - e->ptr));
  71. char *new_buf = upb_realloc(e->alloc, e->buf, old_size, new_size);
  72. if (!new_buf) encode_err(e);
  73. /* We want previous data at the end, realloc() put it at the beginning. */
  74. if (old_size > 0) {
  75. memmove(new_buf + new_size - old_size, e->buf, old_size);
  76. }
  77. e->ptr = new_buf + new_size - (e->limit - e->ptr);
  78. e->limit = new_buf + new_size;
  79. e->buf = new_buf;
  80. e->ptr -= bytes;
  81. }
  82. /* Call to ensure that at least "bytes" bytes are available for writing at
  83. * e->ptr. Returns false if the bytes could not be allocated. */
  84. UPB_FORCEINLINE
  85. static void encode_reserve(upb_encstate *e, size_t bytes) {
  86. if ((size_t)(e->ptr - e->buf) < bytes) {
  87. encode_growbuffer(e, bytes);
  88. return;
  89. }
  90. e->ptr -= bytes;
  91. }
  92. /* Writes the given bytes to the buffer, handling reserve/advance. */
  93. static void encode_bytes(upb_encstate *e, const void *data, size_t len) {
  94. if (len == 0) return; /* memcpy() with zero size is UB */
  95. encode_reserve(e, len);
  96. memcpy(e->ptr, data, len);
  97. }
  98. static void encode_fixed64(upb_encstate *e, uint64_t val) {
  99. val = _upb_be_swap64(val);
  100. encode_bytes(e, &val, sizeof(uint64_t));
  101. }
  102. static void encode_fixed32(upb_encstate *e, uint32_t val) {
  103. val = _upb_be_swap32(val);
  104. encode_bytes(e, &val, sizeof(uint32_t));
  105. }
  106. UPB_NOINLINE
  107. static void encode_longvarint(upb_encstate *e, uint64_t val) {
  108. size_t len;
  109. char *start;
  110. encode_reserve(e, UPB_PB_VARINT_MAX_LEN);
  111. len = encode_varint64(val, e->ptr);
  112. start = e->ptr + UPB_PB_VARINT_MAX_LEN - len;
  113. memmove(start, e->ptr, len);
  114. e->ptr = start;
  115. }
  116. UPB_FORCEINLINE
  117. static void encode_varint(upb_encstate *e, uint64_t val) {
  118. if (val < 128 && e->ptr != e->buf) {
  119. --e->ptr;
  120. *e->ptr = val;
  121. } else {
  122. encode_longvarint(e, val);
  123. }
  124. }
  125. static void encode_double(upb_encstate *e, double d) {
  126. uint64_t u64;
  127. UPB_ASSERT(sizeof(double) == sizeof(uint64_t));
  128. memcpy(&u64, &d, sizeof(uint64_t));
  129. encode_fixed64(e, u64);
  130. }
  131. static void encode_float(upb_encstate *e, float d) {
  132. uint32_t u32;
  133. UPB_ASSERT(sizeof(float) == sizeof(uint32_t));
  134. memcpy(&u32, &d, sizeof(uint32_t));
  135. encode_fixed32(e, u32);
  136. }
  137. static void encode_tag(upb_encstate *e, uint32_t field_number,
  138. uint8_t wire_type) {
  139. encode_varint(e, (field_number << 3) | wire_type);
  140. }
  141. static void encode_fixedarray(upb_encstate *e, const upb_array *arr,
  142. size_t elem_size, uint32_t tag) {
  143. size_t bytes = arr->len * elem_size;
  144. const char* data = _upb_array_constptr(arr);
  145. const char* ptr = data + bytes - elem_size;
  146. if (tag) {
  147. while (true) {
  148. encode_bytes(e, ptr, elem_size);
  149. encode_varint(e, tag);
  150. if (ptr == data) break;
  151. ptr -= elem_size;
  152. }
  153. } else {
  154. encode_bytes(e, data, bytes);
  155. }
  156. }
  157. static void encode_message(upb_encstate *e, const upb_msg *msg,
  158. const upb_msglayout *m, size_t *size);
  159. static void encode_scalar(upb_encstate *e, const void *_field_mem,
  160. const upb_msglayout_sub *subs,
  161. const upb_msglayout_field *f) {
  162. const char *field_mem = _field_mem;
  163. int wire_type;
  164. #define CASE(ctype, type, wtype, encodeval) \
  165. { \
  166. ctype val = *(ctype *)field_mem; \
  167. encode_##type(e, encodeval); \
  168. wire_type = wtype; \
  169. break; \
  170. }
  171. switch (f->descriptortype) {
  172. case UPB_DESCRIPTOR_TYPE_DOUBLE:
  173. CASE(double, double, UPB_WIRE_TYPE_64BIT, val);
  174. case UPB_DESCRIPTOR_TYPE_FLOAT:
  175. CASE(float, float, UPB_WIRE_TYPE_32BIT, val);
  176. case UPB_DESCRIPTOR_TYPE_INT64:
  177. case UPB_DESCRIPTOR_TYPE_UINT64:
  178. CASE(uint64_t, varint, UPB_WIRE_TYPE_VARINT, val);
  179. case UPB_DESCRIPTOR_TYPE_UINT32:
  180. CASE(uint32_t, varint, UPB_WIRE_TYPE_VARINT, val);
  181. case UPB_DESCRIPTOR_TYPE_INT32:
  182. case UPB_DESCRIPTOR_TYPE_ENUM:
  183. CASE(int32_t, varint, UPB_WIRE_TYPE_VARINT, (int64_t)val);
  184. case UPB_DESCRIPTOR_TYPE_SFIXED64:
  185. case UPB_DESCRIPTOR_TYPE_FIXED64:
  186. CASE(uint64_t, fixed64, UPB_WIRE_TYPE_64BIT, val);
  187. case UPB_DESCRIPTOR_TYPE_FIXED32:
  188. case UPB_DESCRIPTOR_TYPE_SFIXED32:
  189. CASE(uint32_t, fixed32, UPB_WIRE_TYPE_32BIT, val);
  190. case UPB_DESCRIPTOR_TYPE_BOOL:
  191. CASE(bool, varint, UPB_WIRE_TYPE_VARINT, val);
  192. case UPB_DESCRIPTOR_TYPE_SINT32:
  193. CASE(int32_t, varint, UPB_WIRE_TYPE_VARINT, encode_zz32(val));
  194. case UPB_DESCRIPTOR_TYPE_SINT64:
  195. CASE(int64_t, varint, UPB_WIRE_TYPE_VARINT, encode_zz64(val));
  196. case UPB_DESCRIPTOR_TYPE_STRING:
  197. case UPB_DESCRIPTOR_TYPE_BYTES: {
  198. upb_strview view = *(upb_strview*)field_mem;
  199. encode_bytes(e, view.data, view.size);
  200. encode_varint(e, view.size);
  201. wire_type = UPB_WIRE_TYPE_DELIMITED;
  202. break;
  203. }
  204. case UPB_DESCRIPTOR_TYPE_GROUP: {
  205. size_t size;
  206. void *submsg = *(void **)field_mem;
  207. const upb_msglayout *subm = subs[f->submsg_index].submsg;
  208. if (submsg == NULL) {
  209. return;
  210. }
  211. if (--e->depth == 0) encode_err(e);
  212. encode_tag(e, f->number, UPB_WIRE_TYPE_END_GROUP);
  213. encode_message(e, submsg, subm, &size);
  214. wire_type = UPB_WIRE_TYPE_START_GROUP;
  215. e->depth++;
  216. break;
  217. }
  218. case UPB_DESCRIPTOR_TYPE_MESSAGE: {
  219. size_t size;
  220. void *submsg = *(void **)field_mem;
  221. const upb_msglayout *subm = subs[f->submsg_index].submsg;
  222. if (submsg == NULL) {
  223. return;
  224. }
  225. if (--e->depth == 0) encode_err(e);
  226. encode_message(e, submsg, subm, &size);
  227. encode_varint(e, size);
  228. wire_type = UPB_WIRE_TYPE_DELIMITED;
  229. e->depth++;
  230. break;
  231. }
  232. default:
  233. UPB_UNREACHABLE();
  234. }
  235. #undef CASE
  236. encode_tag(e, f->number, wire_type);
  237. }
  238. static void encode_array(upb_encstate *e, const upb_msg *msg,
  239. const upb_msglayout_sub *subs,
  240. const upb_msglayout_field *f) {
  241. const upb_array *arr = *UPB_PTR_AT(msg, f->offset, upb_array*);
  242. bool packed = f->mode & _UPB_MODE_IS_PACKED;
  243. size_t pre_len = e->limit - e->ptr;
  244. if (arr == NULL || arr->len == 0) {
  245. return;
  246. }
  247. #define VARINT_CASE(ctype, encode) \
  248. { \
  249. const ctype *start = _upb_array_constptr(arr); \
  250. const ctype *ptr = start + arr->len; \
  251. uint32_t tag = packed ? 0 : (f->number << 3) | UPB_WIRE_TYPE_VARINT; \
  252. do { \
  253. ptr--; \
  254. encode_varint(e, encode); \
  255. if (tag) encode_varint(e, tag); \
  256. } while (ptr != start); \
  257. } \
  258. break;
  259. #define TAG(wire_type) (packed ? 0 : (f->number << 3 | wire_type))
  260. switch (f->descriptortype) {
  261. case UPB_DESCRIPTOR_TYPE_DOUBLE:
  262. encode_fixedarray(e, arr, sizeof(double), TAG(UPB_WIRE_TYPE_64BIT));
  263. break;
  264. case UPB_DESCRIPTOR_TYPE_FLOAT:
  265. encode_fixedarray(e, arr, sizeof(float), TAG(UPB_WIRE_TYPE_32BIT));
  266. break;
  267. case UPB_DESCRIPTOR_TYPE_SFIXED64:
  268. case UPB_DESCRIPTOR_TYPE_FIXED64:
  269. encode_fixedarray(e, arr, sizeof(uint64_t), TAG(UPB_WIRE_TYPE_64BIT));
  270. break;
  271. case UPB_DESCRIPTOR_TYPE_FIXED32:
  272. case UPB_DESCRIPTOR_TYPE_SFIXED32:
  273. encode_fixedarray(e, arr, sizeof(uint32_t), TAG(UPB_WIRE_TYPE_32BIT));
  274. break;
  275. case UPB_DESCRIPTOR_TYPE_INT64:
  276. case UPB_DESCRIPTOR_TYPE_UINT64:
  277. VARINT_CASE(uint64_t, *ptr);
  278. case UPB_DESCRIPTOR_TYPE_UINT32:
  279. VARINT_CASE(uint32_t, *ptr);
  280. case UPB_DESCRIPTOR_TYPE_INT32:
  281. case UPB_DESCRIPTOR_TYPE_ENUM:
  282. VARINT_CASE(int32_t, (int64_t)*ptr);
  283. case UPB_DESCRIPTOR_TYPE_BOOL:
  284. VARINT_CASE(bool, *ptr);
  285. case UPB_DESCRIPTOR_TYPE_SINT32:
  286. VARINT_CASE(int32_t, encode_zz32(*ptr));
  287. case UPB_DESCRIPTOR_TYPE_SINT64:
  288. VARINT_CASE(int64_t, encode_zz64(*ptr));
  289. case UPB_DESCRIPTOR_TYPE_STRING:
  290. case UPB_DESCRIPTOR_TYPE_BYTES: {
  291. const upb_strview *start = _upb_array_constptr(arr);
  292. const upb_strview *ptr = start + arr->len;
  293. do {
  294. ptr--;
  295. encode_bytes(e, ptr->data, ptr->size);
  296. encode_varint(e, ptr->size);
  297. encode_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED);
  298. } while (ptr != start);
  299. return;
  300. }
  301. case UPB_DESCRIPTOR_TYPE_GROUP: {
  302. const void *const*start = _upb_array_constptr(arr);
  303. const void *const*ptr = start + arr->len;
  304. const upb_msglayout *subm = subs[f->submsg_index].submsg;
  305. if (--e->depth == 0) encode_err(e);
  306. do {
  307. size_t size;
  308. ptr--;
  309. encode_tag(e, f->number, UPB_WIRE_TYPE_END_GROUP);
  310. encode_message(e, *ptr, subm, &size);
  311. encode_tag(e, f->number, UPB_WIRE_TYPE_START_GROUP);
  312. } while (ptr != start);
  313. e->depth++;
  314. return;
  315. }
  316. case UPB_DESCRIPTOR_TYPE_MESSAGE: {
  317. const void *const*start = _upb_array_constptr(arr);
  318. const void *const*ptr = start + arr->len;
  319. const upb_msglayout *subm = subs[f->submsg_index].submsg;
  320. if (--e->depth == 0) encode_err(e);
  321. do {
  322. size_t size;
  323. ptr--;
  324. encode_message(e, *ptr, subm, &size);
  325. encode_varint(e, size);
  326. encode_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED);
  327. } while (ptr != start);
  328. e->depth++;
  329. return;
  330. }
  331. }
  332. #undef VARINT_CASE
  333. if (packed) {
  334. encode_varint(e, e->limit - e->ptr - pre_len);
  335. encode_tag(e, f->number, UPB_WIRE_TYPE_DELIMITED);
  336. }
  337. }
  338. static void encode_mapentry(upb_encstate *e, uint32_t number,
  339. const upb_msglayout *layout,
  340. const upb_map_entry *ent) {
  341. const upb_msglayout_field *key_field = &layout->fields[0];
  342. const upb_msglayout_field *val_field = &layout->fields[1];
  343. size_t pre_len = e->limit - e->ptr;
  344. size_t size;
  345. encode_scalar(e, &ent->v, layout->subs, val_field);
  346. encode_scalar(e, &ent->k, layout->subs, key_field);
  347. size = (e->limit - e->ptr) - pre_len;
  348. encode_varint(e, size);
  349. encode_tag(e, number, UPB_WIRE_TYPE_DELIMITED);
  350. }
  351. static void encode_map(upb_encstate *e, const upb_msg *msg,
  352. const upb_msglayout_sub *subs,
  353. const upb_msglayout_field *f) {
  354. const upb_map *map = *UPB_PTR_AT(msg, f->offset, const upb_map*);
  355. const upb_msglayout *layout = subs[f->submsg_index].submsg;
  356. UPB_ASSERT(layout->field_count == 2);
  357. if (map == NULL) return;
  358. if (e->options & UPB_ENCODE_DETERMINISTIC) {
  359. _upb_sortedmap sorted;
  360. _upb_mapsorter_pushmap(&e->sorter, layout->fields[0].descriptortype, map,
  361. &sorted);
  362. upb_map_entry ent;
  363. while (_upb_sortedmap_next(&e->sorter, map, &sorted, &ent)) {
  364. encode_mapentry(e, f->number, layout, &ent);
  365. }
  366. _upb_mapsorter_popmap(&e->sorter, &sorted);
  367. } else {
  368. upb_strtable_iter i;
  369. upb_strtable_begin(&i, &map->table);
  370. for(; !upb_strtable_done(&i); upb_strtable_next(&i)) {
  371. upb_strview key = upb_strtable_iter_key(&i);
  372. const upb_value val = upb_strtable_iter_value(&i);
  373. upb_map_entry ent;
  374. _upb_map_fromkey(key, &ent.k, map->key_size);
  375. _upb_map_fromvalue(val, &ent.v, map->val_size);
  376. encode_mapentry(e, f->number, layout, &ent);
  377. }
  378. }
  379. }
  380. static bool encode_shouldencode(upb_encstate *e, const upb_msg *msg,
  381. const upb_msglayout_sub *subs,
  382. const upb_msglayout_field *f) {
  383. if (f->presence == 0) {
  384. /* Proto3 presence or map/array. */
  385. const void *mem = UPB_PTR_AT(msg, f->offset, void);
  386. switch (f->mode >> _UPB_REP_SHIFT) {
  387. case _UPB_REP_1BYTE: {
  388. char ch;
  389. memcpy(&ch, mem, 1);
  390. return ch != 0;
  391. }
  392. case _UPB_REP_4BYTE: {
  393. uint32_t u32;
  394. memcpy(&u32, mem, 4);
  395. return u32 != 0;
  396. }
  397. case _UPB_REP_8BYTE: {
  398. uint64_t u64;
  399. memcpy(&u64, mem, 8);
  400. return u64 != 0;
  401. }
  402. case _UPB_REP_STRVIEW: {
  403. const upb_strview *str = (const upb_strview*)mem;
  404. return str->size != 0;
  405. }
  406. default:
  407. UPB_UNREACHABLE();
  408. }
  409. } else if (f->presence > 0) {
  410. /* Proto2 presence: hasbit. */
  411. return _upb_hasbit_field(msg, f);
  412. } else {
  413. /* Field is in a oneof. */
  414. return _upb_getoneofcase_field(msg, f) == f->number;
  415. }
  416. }
  417. static void encode_field(upb_encstate *e, const upb_msg *msg,
  418. const upb_msglayout_sub *subs,
  419. const upb_msglayout_field *field) {
  420. switch (_upb_getmode(field)) {
  421. case _UPB_MODE_ARRAY:
  422. encode_array(e, msg, subs, field);
  423. break;
  424. case _UPB_MODE_MAP:
  425. encode_map(e, msg, subs, field);
  426. break;
  427. case _UPB_MODE_SCALAR:
  428. encode_scalar(e, UPB_PTR_AT(msg, field->offset, void), subs, field);
  429. break;
  430. default:
  431. UPB_UNREACHABLE();
  432. }
  433. }
  434. /* message MessageSet {
  435. * repeated group Item = 1 {
  436. * required int32 type_id = 2;
  437. * required string message = 3;
  438. * }
  439. * } */
  440. static void encode_msgset_item(upb_encstate *e, const upb_msg_ext *ext) {
  441. size_t size;
  442. encode_tag(e, 1, UPB_WIRE_TYPE_END_GROUP);
  443. encode_message(e, ext->data.ptr, ext->ext->sub.submsg, &size);
  444. encode_varint(e, size);
  445. encode_tag(e, 3, UPB_WIRE_TYPE_DELIMITED);
  446. encode_varint(e, ext->ext->field.number);
  447. encode_tag(e, 2, UPB_WIRE_TYPE_VARINT);
  448. encode_tag(e, 1, UPB_WIRE_TYPE_START_GROUP);
  449. }
  450. static void encode_message(upb_encstate *e, const upb_msg *msg,
  451. const upb_msglayout *m, size_t *size) {
  452. size_t pre_len = e->limit - e->ptr;
  453. if ((e->options & UPB_ENCODE_SKIPUNKNOWN) == 0) {
  454. size_t unknown_size;
  455. const char *unknown = upb_msg_getunknown(msg, &unknown_size);
  456. if (unknown) {
  457. encode_bytes(e, unknown, unknown_size);
  458. }
  459. }
  460. if (m->ext != _UPB_MSGEXT_NONE) {
  461. /* Encode all extensions together. Unlike C++, we do not attempt to keep
  462. * these in field number order relative to normal fields or even to each
  463. * other. */
  464. size_t ext_count;
  465. const upb_msg_ext *ext = _upb_msg_getexts(msg, &ext_count);
  466. const upb_msg_ext *end = ext + ext_count;
  467. if (ext_count) {
  468. for (; ext != end; ext++) {
  469. if (UPB_UNLIKELY(m->ext == _UPB_MSGEXT_MSGSET)) {
  470. encode_msgset_item(e, ext);
  471. } else {
  472. encode_field(e, &ext->data, &ext->ext->sub, &ext->ext->field);
  473. }
  474. }
  475. }
  476. }
  477. const upb_msglayout_field *f = &m->fields[m->field_count];
  478. const upb_msglayout_field *first = &m->fields[0];
  479. while (f != first) {
  480. f--;
  481. if (encode_shouldencode(e, msg, m->subs, f)) {
  482. encode_field(e, msg, m->subs, f);
  483. }
  484. }
  485. *size = (e->limit - e->ptr) - pre_len;
  486. }
  487. char *upb_encode_ex(const void *msg, const upb_msglayout *l, int options,
  488. upb_arena *arena, size_t *size) {
  489. upb_encstate e;
  490. unsigned depth = (unsigned)options >> 16;
  491. e.alloc = upb_arena_alloc(arena);
  492. e.buf = NULL;
  493. e.limit = NULL;
  494. e.ptr = NULL;
  495. e.depth = depth ? depth : 64;
  496. e.options = options;
  497. _upb_mapsorter_init(&e.sorter);
  498. char *ret = NULL;
  499. if (UPB_SETJMP(e.err)) {
  500. *size = 0;
  501. ret = NULL;
  502. } else {
  503. encode_message(&e, msg, l, size);
  504. *size = e.limit - e.ptr;
  505. if (*size == 0) {
  506. static char ch;
  507. ret = &ch;
  508. } else {
  509. UPB_ASSERT(e.ptr);
  510. ret = e.ptr;
  511. }
  512. }
  513. _upb_mapsorter_destroy(&e.sorter);
  514. return ret;
  515. }