blob: 212f1e0e6b3ac4e5ca8b8e86960d2f0ce4cacf6d [file] [log] [blame]
Chris Fallin91473dc2014-12-12 15:58:26 -08001// Amalgamated source file
2#include "upb.h"
Chris Fallin91473dc2014-12-12 15:58:26 -08003
4
Josh Haberman78da6662016-01-13 19:05:43 -08005#include <ctype.h>
Chris Fallin91473dc2014-12-12 15:58:26 -08006#include <stdlib.h>
7#include <string.h>
8
9typedef struct {
10 size_t len;
Josh Habermane8ed0212015-06-08 17:56:03 -070011 char str[1]; /* Null-terminated string data follows. */
Chris Fallin91473dc2014-12-12 15:58:26 -080012} str_t;
13
14static str_t *newstr(const char *data, size_t len) {
15 str_t *ret = malloc(sizeof(*ret) + len);
16 if (!ret) return NULL;
17 ret->len = len;
18 memcpy(ret->str, data, len);
19 ret->str[len] = '\0';
20 return ret;
21}
22
23static void freestr(str_t *s) { free(s); }
24
Josh Habermane8ed0212015-06-08 17:56:03 -070025/* isalpha() etc. from <ctype.h> are locale-dependent, which we don't want. */
Chris Fallin91473dc2014-12-12 15:58:26 -080026static bool upb_isbetween(char c, char low, char high) {
27 return c >= low && c <= high;
28}
29
30static bool upb_isletter(char c) {
31 return upb_isbetween(c, 'A', 'Z') || upb_isbetween(c, 'a', 'z') || c == '_';
32}
33
34static bool upb_isalphanum(char c) {
35 return upb_isletter(c) || upb_isbetween(c, '0', '9');
36}
37
38static bool upb_isident(const char *str, size_t len, bool full, upb_status *s) {
39 bool start = true;
Josh Habermane8ed0212015-06-08 17:56:03 -070040 size_t i;
41 for (i = 0; i < len; i++) {
Chris Fallin91473dc2014-12-12 15:58:26 -080042 char c = str[i];
43 if (c == '.') {
44 if (start || !full) {
45 upb_status_seterrf(s, "invalid name: unexpected '.' (%s)", str);
46 return false;
47 }
48 start = true;
49 } else if (start) {
50 if (!upb_isletter(c)) {
51 upb_status_seterrf(
52 s, "invalid name: path components must start with a letter (%s)",
53 str);
54 return false;
55 }
56 start = false;
57 } else {
58 if (!upb_isalphanum(c)) {
59 upb_status_seterrf(s, "invalid name: non-alphanumeric character (%s)",
60 str);
61 return false;
62 }
63 }
64 }
65 return !start;
66}
67
68
69/* upb_def ********************************************************************/
70
71upb_deftype_t upb_def_type(const upb_def *d) { return d->type; }
72
73const char *upb_def_fullname(const upb_def *d) { return d->fullname; }
74
Josh Haberman94e54b32016-04-14 12:06:09 -070075const char *upb_def_name(const upb_def *d) {
76 const char *p;
77
78 if (d->fullname == NULL) {
79 return NULL;
80 } else if ((p = strrchr(d->fullname, '.')) == NULL) {
81 /* No '.' in the name, return the full string. */
82 return d->fullname;
83 } else {
84 /* Return one past the last '.'. */
85 return p + 1;
86 }
87}
88
Chris Fallin91473dc2014-12-12 15:58:26 -080089bool upb_def_setfullname(upb_def *def, const char *fullname, upb_status *s) {
90 assert(!upb_def_isfrozen(def));
91 if (!upb_isident(fullname, strlen(fullname), true, s)) return false;
92 free((void*)def->fullname);
93 def->fullname = upb_strdup(fullname);
94 return true;
95}
96
Josh Haberman94e54b32016-04-14 12:06:09 -070097const upb_filedef *upb_def_file(const upb_def *d) { return d->file; }
98
Chris Fallin91473dc2014-12-12 15:58:26 -080099upb_def *upb_def_dup(const upb_def *def, const void *o) {
100 switch (def->type) {
101 case UPB_DEF_MSG:
Josh Habermane8ed0212015-06-08 17:56:03 -0700102 return upb_msgdef_upcast_mutable(
103 upb_msgdef_dup(upb_downcast_msgdef(def), o));
Chris Fallin91473dc2014-12-12 15:58:26 -0800104 case UPB_DEF_FIELD:
Josh Habermane8ed0212015-06-08 17:56:03 -0700105 return upb_fielddef_upcast_mutable(
106 upb_fielddef_dup(upb_downcast_fielddef(def), o));
Chris Fallin91473dc2014-12-12 15:58:26 -0800107 case UPB_DEF_ENUM:
Josh Habermane8ed0212015-06-08 17:56:03 -0700108 return upb_enumdef_upcast_mutable(
109 upb_enumdef_dup(upb_downcast_enumdef(def), o));
Chris Fallin91473dc2014-12-12 15:58:26 -0800110 default: assert(false); return NULL;
111 }
112}
113
Chris Fallin91473dc2014-12-12 15:58:26 -0800114static bool upb_def_init(upb_def *def, upb_deftype_t type,
115 const struct upb_refcounted_vtbl *vtbl,
116 const void *owner) {
Josh Habermane8ed0212015-06-08 17:56:03 -0700117 if (!upb_refcounted_init(upb_def_upcast_mutable(def), vtbl, owner)) return false;
Chris Fallin91473dc2014-12-12 15:58:26 -0800118 def->type = type;
119 def->fullname = NULL;
120 def->came_from_user = false;
Josh Haberman94e54b32016-04-14 12:06:09 -0700121 def->file = NULL;
Chris Fallin91473dc2014-12-12 15:58:26 -0800122 return true;
123}
124
125static void upb_def_uninit(upb_def *def) {
126 free((void*)def->fullname);
127}
128
129static const char *msgdef_name(const upb_msgdef *m) {
Josh Habermane8ed0212015-06-08 17:56:03 -0700130 const char *name = upb_def_fullname(upb_msgdef_upcast(m));
Chris Fallin91473dc2014-12-12 15:58:26 -0800131 return name ? name : "(anonymous)";
132}
133
134static bool upb_validate_field(upb_fielddef *f, upb_status *s) {
135 if (upb_fielddef_name(f) == NULL || upb_fielddef_number(f) == 0) {
136 upb_status_seterrmsg(s, "fielddef must have name and number set");
137 return false;
138 }
139
140 if (!f->type_is_set_) {
141 upb_status_seterrmsg(s, "fielddef type was not initialized");
142 return false;
143 }
144
145 if (upb_fielddef_lazy(f) &&
146 upb_fielddef_descriptortype(f) != UPB_DESCRIPTOR_TYPE_MESSAGE) {
147 upb_status_seterrmsg(s,
148 "only length-delimited submessage fields may be lazy");
149 return false;
150 }
151
152 if (upb_fielddef_hassubdef(f)) {
Josh Habermane8ed0212015-06-08 17:56:03 -0700153 const upb_def *subdef;
154
Chris Fallin91473dc2014-12-12 15:58:26 -0800155 if (f->subdef_is_symbolic) {
156 upb_status_seterrf(s, "field '%s.%s' has not been resolved",
157 msgdef_name(f->msg.def), upb_fielddef_name(f));
158 return false;
159 }
160
Josh Habermane8ed0212015-06-08 17:56:03 -0700161 subdef = upb_fielddef_subdef(f);
Chris Fallin91473dc2014-12-12 15:58:26 -0800162 if (subdef == NULL) {
163 upb_status_seterrf(s, "field %s.%s is missing required subdef",
164 msgdef_name(f->msg.def), upb_fielddef_name(f));
165 return false;
166 }
167
168 if (!upb_def_isfrozen(subdef) && !subdef->came_from_user) {
169 upb_status_seterrf(s,
170 "subdef of field %s.%s is not frozen or being frozen",
171 msgdef_name(f->msg.def), upb_fielddef_name(f));
172 return false;
173 }
174 }
175
176 if (upb_fielddef_type(f) == UPB_TYPE_ENUM) {
177 bool has_default_name = upb_fielddef_enumhasdefaultstr(f);
178 bool has_default_number = upb_fielddef_enumhasdefaultint32(f);
179
Josh Habermane8ed0212015-06-08 17:56:03 -0700180 /* Previously verified by upb_validate_enumdef(). */
Chris Fallin91473dc2014-12-12 15:58:26 -0800181 assert(upb_enumdef_numvals(upb_fielddef_enumsubdef(f)) > 0);
182
Josh Habermane8ed0212015-06-08 17:56:03 -0700183 /* We've already validated that we have an associated enumdef and that it
184 * has at least one member, so at least one of these should be true.
185 * Because if the user didn't set anything, we'll pick up the enum's
186 * default, but if the user *did* set something we should at least pick up
187 * the one they set (int32 or string). */
Chris Fallin91473dc2014-12-12 15:58:26 -0800188 assert(has_default_name || has_default_number);
189
190 if (!has_default_name) {
191 upb_status_seterrf(s,
192 "enum default for field %s.%s (%d) is not in the enum",
193 msgdef_name(f->msg.def), upb_fielddef_name(f),
194 upb_fielddef_defaultint32(f));
195 return false;
196 }
197
198 if (!has_default_number) {
199 upb_status_seterrf(s,
200 "enum default for field %s.%s (%s) is not in the enum",
201 msgdef_name(f->msg.def), upb_fielddef_name(f),
202 upb_fielddef_defaultstr(f, NULL));
203 return false;
204 }
205
Josh Habermane8ed0212015-06-08 17:56:03 -0700206 /* Lift the effective numeric default into the field's default slot, in case
207 * we were only getting it "by reference" from the enumdef. */
Chris Fallin91473dc2014-12-12 15:58:26 -0800208 upb_fielddef_setdefaultint32(f, upb_fielddef_defaultint32(f));
209 }
210
Josh Habermane8ed0212015-06-08 17:56:03 -0700211 /* Ensure that MapEntry submessages only appear as repeated fields, not
212 * optional/required (singular) fields. */
Chris Fallina5075922015-02-02 15:07:34 -0800213 if (upb_fielddef_type(f) == UPB_TYPE_MESSAGE &&
214 upb_fielddef_msgsubdef(f) != NULL) {
215 const upb_msgdef *subdef = upb_fielddef_msgsubdef(f);
216 if (upb_msgdef_mapentry(subdef) && !upb_fielddef_isseq(f)) {
217 upb_status_seterrf(s,
218 "Field %s refers to mapentry message but is not "
219 "a repeated field",
220 upb_fielddef_name(f) ? upb_fielddef_name(f) :
221 "(unnamed)");
222 return false;
223 }
224 }
225
Chris Fallin91473dc2014-12-12 15:58:26 -0800226 return true;
227}
228
229static bool upb_validate_enumdef(const upb_enumdef *e, upb_status *s) {
230 if (upb_enumdef_numvals(e) == 0) {
231 upb_status_seterrf(s, "enum %s has no members (must have at least one)",
232 upb_enumdef_fullname(e));
233 return false;
234 }
235
236 return true;
237}
238
Josh Habermane8ed0212015-06-08 17:56:03 -0700239/* All submessage fields are lower than all other fields.
240 * Secondly, fields are increasing in order. */
Chris Fallin91473dc2014-12-12 15:58:26 -0800241uint32_t field_rank(const upb_fielddef *f) {
242 uint32_t ret = upb_fielddef_number(f);
243 const uint32_t high_bit = 1 << 30;
244 assert(ret < high_bit);
245 if (!upb_fielddef_issubmsg(f))
246 ret |= high_bit;
247 return ret;
248}
249
250int cmp_fields(const void *p1, const void *p2) {
251 const upb_fielddef *f1 = *(upb_fielddef*const*)p1;
252 const upb_fielddef *f2 = *(upb_fielddef*const*)p2;
253 return field_rank(f1) - field_rank(f2);
254}
255
256static bool assign_msg_indices(upb_msgdef *m, upb_status *s) {
Josh Habermane8ed0212015-06-08 17:56:03 -0700257 /* Sort fields. upb internally relies on UPB_TYPE_MESSAGE fields having the
258 * lowest indexes, but we do not publicly guarantee this. */
259 upb_msg_field_iter j;
260 int i;
261 uint32_t selector;
Chris Fallin91473dc2014-12-12 15:58:26 -0800262 int n = upb_msgdef_numfields(m);
263 upb_fielddef **fields = malloc(n * sizeof(*fields));
264 if (!fields) return false;
265
Chris Fallin91473dc2014-12-12 15:58:26 -0800266 m->submsg_field_count = 0;
Chris Fallinfcd88892015-01-13 18:14:39 -0800267 for(i = 0, upb_msg_field_begin(&j, m);
268 !upb_msg_field_done(&j);
269 upb_msg_field_next(&j), i++) {
Chris Fallin91473dc2014-12-12 15:58:26 -0800270 upb_fielddef *f = upb_msg_iter_field(&j);
271 assert(f->msg.def == m);
272 if (!upb_validate_field(f, s)) {
273 free(fields);
274 return false;
275 }
276 if (upb_fielddef_issubmsg(f)) {
277 m->submsg_field_count++;
278 }
279 fields[i] = f;
280 }
281
282 qsort(fields, n, sizeof(*fields), cmp_fields);
283
Josh Habermane8ed0212015-06-08 17:56:03 -0700284 selector = UPB_STATIC_SELECTOR_COUNT + m->submsg_field_count;
Chris Fallin91473dc2014-12-12 15:58:26 -0800285 for (i = 0; i < n; i++) {
286 upb_fielddef *f = fields[i];
287 f->index_ = i;
288 f->selector_base = selector + upb_handlers_selectorbaseoffset(f);
289 selector += upb_handlers_selectorcount(f);
290 }
291 m->selector_count = selector;
292
293#ifndef NDEBUG
Josh Habermane8ed0212015-06-08 17:56:03 -0700294 {
295 /* Verify that all selectors for the message are distinct. */
Chris Fallin91473dc2014-12-12 15:58:26 -0800296#define TRY(type) \
Josh Habermane8ed0212015-06-08 17:56:03 -0700297 if (upb_handlers_getselector(f, type, &sel)) upb_inttable_insert(&t, sel, v);
Chris Fallin91473dc2014-12-12 15:58:26 -0800298
Josh Habermane8ed0212015-06-08 17:56:03 -0700299 upb_inttable t;
300 upb_value v;
301 upb_selector_t sel;
302
303 upb_inttable_init(&t, UPB_CTYPE_BOOL);
304 v = upb_value_bool(true);
305 upb_inttable_insert(&t, UPB_STARTMSG_SELECTOR, v);
306 upb_inttable_insert(&t, UPB_ENDMSG_SELECTOR, v);
307 for(upb_msg_field_begin(&j, m);
308 !upb_msg_field_done(&j);
309 upb_msg_field_next(&j)) {
310 upb_fielddef *f = upb_msg_iter_field(&j);
311 /* These calls will assert-fail in upb_table if the value already
312 * exists. */
313 TRY(UPB_HANDLER_INT32);
314 TRY(UPB_HANDLER_INT64)
315 TRY(UPB_HANDLER_UINT32)
316 TRY(UPB_HANDLER_UINT64)
317 TRY(UPB_HANDLER_FLOAT)
318 TRY(UPB_HANDLER_DOUBLE)
319 TRY(UPB_HANDLER_BOOL)
320 TRY(UPB_HANDLER_STARTSTR)
321 TRY(UPB_HANDLER_STRING)
322 TRY(UPB_HANDLER_ENDSTR)
323 TRY(UPB_HANDLER_STARTSUBMSG)
324 TRY(UPB_HANDLER_ENDSUBMSG)
325 TRY(UPB_HANDLER_STARTSEQ)
326 TRY(UPB_HANDLER_ENDSEQ)
327 }
328 upb_inttable_uninit(&t);
Chris Fallin91473dc2014-12-12 15:58:26 -0800329 }
Chris Fallin91473dc2014-12-12 15:58:26 -0800330#undef TRY
331#endif
332
333 free(fields);
334 return true;
335}
336
Josh Haberman94e54b32016-04-14 12:06:09 -0700337bool _upb_def_validate(upb_def *const*defs, size_t n, upb_status *s) {
338 size_t i;
Chris Fallin91473dc2014-12-12 15:58:26 -0800339
Josh Habermane8ed0212015-06-08 17:56:03 -0700340 /* First perform validation, in two passes so we can check that we have a
341 * transitive closure without needing to search. */
342 for (i = 0; i < n; i++) {
Chris Fallin91473dc2014-12-12 15:58:26 -0800343 upb_def *def = defs[i];
344 if (upb_def_isfrozen(def)) {
Josh Habermane8ed0212015-06-08 17:56:03 -0700345 /* Could relax this requirement if it's annoying. */
Chris Fallin91473dc2014-12-12 15:58:26 -0800346 upb_status_seterrmsg(s, "def is already frozen");
347 goto err;
348 } else if (def->type == UPB_DEF_FIELD) {
349 upb_status_seterrmsg(s, "standalone fielddefs can not be frozen");
350 goto err;
351 } else if (def->type == UPB_DEF_ENUM) {
352 if (!upb_validate_enumdef(upb_dyncast_enumdef(def), s)) {
353 goto err;
354 }
355 } else {
Josh Habermane8ed0212015-06-08 17:56:03 -0700356 /* Set now to detect transitive closure in the second pass. */
Chris Fallin91473dc2014-12-12 15:58:26 -0800357 def->came_from_user = true;
358 }
359 }
360
Josh Habermane8ed0212015-06-08 17:56:03 -0700361 /* Second pass of validation. Also assign selector bases and indexes, and
362 * compact tables. */
363 for (i = 0; i < n; i++) {
Josh Haberman94e54b32016-04-14 12:06:09 -0700364 upb_def *def = defs[i];
365 upb_msgdef *m = upb_dyncast_msgdef_mutable(def);
366 upb_enumdef *e = upb_dyncast_enumdef_mutable(def);
Chris Fallin91473dc2014-12-12 15:58:26 -0800367 if (m) {
368 upb_inttable_compact(&m->itof);
369 if (!assign_msg_indices(m, s)) {
370 goto err;
371 }
372 } else if (e) {
373 upb_inttable_compact(&e->iton);
374 }
375 }
376
Josh Haberman94e54b32016-04-14 12:06:09 -0700377 return true;
Chris Fallin91473dc2014-12-12 15:58:26 -0800378
379err:
Josh Habermane8ed0212015-06-08 17:56:03 -0700380 for (i = 0; i < n; i++) {
Josh Haberman94e54b32016-04-14 12:06:09 -0700381 upb_def *def = defs[i];
382 def->came_from_user = false;
Chris Fallin91473dc2014-12-12 15:58:26 -0800383 }
384 assert(!(s && upb_ok(s)));
385 return false;
386}
387
Josh Haberman94e54b32016-04-14 12:06:09 -0700388bool upb_def_freeze(upb_def *const* defs, size_t n, upb_status *s) {
389 /* Def graph contains FieldDefs between each MessageDef, so double the
390 * limit. */
391 const size_t maxdepth = UPB_MAX_MESSAGE_DEPTH * 2;
392
393 if (!_upb_def_validate(defs, n, s)) {
394 return false;
395 }
396
397
398 /* Validation all passed; freeze the objects. */
399 return upb_refcounted_freeze((upb_refcounted *const*)defs, n, s, maxdepth);
400}
401
Chris Fallin91473dc2014-12-12 15:58:26 -0800402
403/* upb_enumdef ****************************************************************/
404
405static void upb_enumdef_free(upb_refcounted *r) {
406 upb_enumdef *e = (upb_enumdef*)r;
407 upb_inttable_iter i;
408 upb_inttable_begin(&i, &e->iton);
409 for( ; !upb_inttable_done(&i); upb_inttable_next(&i)) {
Josh Habermane8ed0212015-06-08 17:56:03 -0700410 /* To clean up the upb_strdup() from upb_enumdef_addval(). */
Chris Fallin91473dc2014-12-12 15:58:26 -0800411 free(upb_value_getcstr(upb_inttable_iter_value(&i)));
412 }
413 upb_strtable_uninit(&e->ntoi);
414 upb_inttable_uninit(&e->iton);
Josh Habermane8ed0212015-06-08 17:56:03 -0700415 upb_def_uninit(upb_enumdef_upcast_mutable(e));
Chris Fallin91473dc2014-12-12 15:58:26 -0800416 free(e);
417}
418
419upb_enumdef *upb_enumdef_new(const void *owner) {
420 static const struct upb_refcounted_vtbl vtbl = {NULL, &upb_enumdef_free};
421 upb_enumdef *e = malloc(sizeof(*e));
422 if (!e) return NULL;
Josh Habermane8ed0212015-06-08 17:56:03 -0700423 if (!upb_def_init(upb_enumdef_upcast_mutable(e), UPB_DEF_ENUM, &vtbl, owner))
424 goto err2;
Chris Fallin91473dc2014-12-12 15:58:26 -0800425 if (!upb_strtable_init(&e->ntoi, UPB_CTYPE_INT32)) goto err2;
426 if (!upb_inttable_init(&e->iton, UPB_CTYPE_CSTR)) goto err1;
427 return e;
428
429err1:
430 upb_strtable_uninit(&e->ntoi);
431err2:
432 free(e);
433 return NULL;
434}
435
436upb_enumdef *upb_enumdef_dup(const upb_enumdef *e, const void *owner) {
Josh Habermane8ed0212015-06-08 17:56:03 -0700437 upb_enum_iter i;
Chris Fallin91473dc2014-12-12 15:58:26 -0800438 upb_enumdef *new_e = upb_enumdef_new(owner);
439 if (!new_e) return NULL;
Chris Fallin91473dc2014-12-12 15:58:26 -0800440 for(upb_enum_begin(&i, e); !upb_enum_done(&i); upb_enum_next(&i)) {
441 bool success = upb_enumdef_addval(
442 new_e, upb_enum_iter_name(&i),upb_enum_iter_number(&i), NULL);
443 if (!success) {
444 upb_enumdef_unref(new_e, owner);
445 return NULL;
446 }
447 }
448 return new_e;
449}
450
Chris Fallin91473dc2014-12-12 15:58:26 -0800451bool upb_enumdef_freeze(upb_enumdef *e, upb_status *status) {
Josh Habermane8ed0212015-06-08 17:56:03 -0700452 upb_def *d = upb_enumdef_upcast_mutable(e);
Chris Fallin91473dc2014-12-12 15:58:26 -0800453 return upb_def_freeze(&d, 1, status);
454}
455
456const char *upb_enumdef_fullname(const upb_enumdef *e) {
Josh Habermane8ed0212015-06-08 17:56:03 -0700457 return upb_def_fullname(upb_enumdef_upcast(e));
Chris Fallin91473dc2014-12-12 15:58:26 -0800458}
459
Josh Haberman94e54b32016-04-14 12:06:09 -0700460const char *upb_enumdef_name(const upb_enumdef *e) {
461 return upb_def_name(upb_enumdef_upcast(e));
462}
463
Chris Fallin91473dc2014-12-12 15:58:26 -0800464bool upb_enumdef_setfullname(upb_enumdef *e, const char *fullname,
465 upb_status *s) {
Josh Habermane8ed0212015-06-08 17:56:03 -0700466 return upb_def_setfullname(upb_enumdef_upcast_mutable(e), fullname, s);
Chris Fallin91473dc2014-12-12 15:58:26 -0800467}
468
469bool upb_enumdef_addval(upb_enumdef *e, const char *name, int32_t num,
470 upb_status *status) {
471 if (!upb_isident(name, strlen(name), false, status)) {
472 return false;
473 }
474 if (upb_enumdef_ntoiz(e, name, NULL)) {
475 upb_status_seterrf(status, "name '%s' is already defined", name);
476 return false;
477 }
478 if (!upb_strtable_insert(&e->ntoi, name, upb_value_int32(num))) {
479 upb_status_seterrmsg(status, "out of memory");
480 return false;
481 }
482 if (!upb_inttable_lookup(&e->iton, num, NULL) &&
483 !upb_inttable_insert(&e->iton, num, upb_value_cstr(upb_strdup(name)))) {
484 upb_status_seterrmsg(status, "out of memory");
485 upb_strtable_remove(&e->ntoi, name, NULL);
486 return false;
487 }
488 if (upb_enumdef_numvals(e) == 1) {
489 bool ok = upb_enumdef_setdefault(e, num, NULL);
490 UPB_ASSERT_VAR(ok, ok);
491 }
492 return true;
493}
494
495int32_t upb_enumdef_default(const upb_enumdef *e) {
496 assert(upb_enumdef_iton(e, e->defaultval));
497 return e->defaultval;
498}
499
500bool upb_enumdef_setdefault(upb_enumdef *e, int32_t val, upb_status *s) {
501 assert(!upb_enumdef_isfrozen(e));
502 if (!upb_enumdef_iton(e, val)) {
503 upb_status_seterrf(s, "number '%d' is not in the enum.", val);
504 return false;
505 }
506 e->defaultval = val;
507 return true;
508}
509
510int upb_enumdef_numvals(const upb_enumdef *e) {
511 return upb_strtable_count(&e->ntoi);
512}
513
514void upb_enum_begin(upb_enum_iter *i, const upb_enumdef *e) {
Josh Habermane8ed0212015-06-08 17:56:03 -0700515 /* We iterate over the ntoi table, to account for duplicate numbers. */
Chris Fallin91473dc2014-12-12 15:58:26 -0800516 upb_strtable_begin(i, &e->ntoi);
517}
518
519void upb_enum_next(upb_enum_iter *iter) { upb_strtable_next(iter); }
520bool upb_enum_done(upb_enum_iter *iter) { return upb_strtable_done(iter); }
521
522bool upb_enumdef_ntoi(const upb_enumdef *def, const char *name,
523 size_t len, int32_t *num) {
524 upb_value v;
525 if (!upb_strtable_lookup2(&def->ntoi, name, len, &v)) {
526 return false;
527 }
528 if (num) *num = upb_value_getint32(v);
529 return true;
530}
531
532const char *upb_enumdef_iton(const upb_enumdef *def, int32_t num) {
533 upb_value v;
534 return upb_inttable_lookup32(&def->iton, num, &v) ?
535 upb_value_getcstr(v) : NULL;
536}
537
538const char *upb_enum_iter_name(upb_enum_iter *iter) {
539 return upb_strtable_iter_key(iter);
540}
541
542int32_t upb_enum_iter_number(upb_enum_iter *iter) {
543 return upb_value_getint32(upb_strtable_iter_value(iter));
544}
545
546
547/* upb_fielddef ***************************************************************/
548
549static void upb_fielddef_init_default(upb_fielddef *f);
550
551static void upb_fielddef_uninit_default(upb_fielddef *f) {
552 if (f->type_is_set_ && f->default_is_string && f->defaultval.bytes)
553 freestr(f->defaultval.bytes);
554}
555
Josh Haberman78da6662016-01-13 19:05:43 -0800556const char *upb_fielddef_fullname(const upb_fielddef *e) {
557 return upb_def_fullname(upb_fielddef_upcast(e));
558}
559
Chris Fallin91473dc2014-12-12 15:58:26 -0800560static void visitfield(const upb_refcounted *r, upb_refcounted_visit *visit,
561 void *closure) {
562 const upb_fielddef *f = (const upb_fielddef*)r;
563 if (upb_fielddef_containingtype(f)) {
Josh Habermane8ed0212015-06-08 17:56:03 -0700564 visit(r, upb_msgdef_upcast2(upb_fielddef_containingtype(f)), closure);
Chris Fallin91473dc2014-12-12 15:58:26 -0800565 }
Chris Fallinfcd88892015-01-13 18:14:39 -0800566 if (upb_fielddef_containingoneof(f)) {
Josh Haberman94e54b32016-04-14 12:06:09 -0700567 visit(r, upb_oneofdef_upcast(upb_fielddef_containingoneof(f)), closure);
Chris Fallinfcd88892015-01-13 18:14:39 -0800568 }
Chris Fallin91473dc2014-12-12 15:58:26 -0800569 if (upb_fielddef_subdef(f)) {
Josh Habermane8ed0212015-06-08 17:56:03 -0700570 visit(r, upb_def_upcast(upb_fielddef_subdef(f)), closure);
Chris Fallin91473dc2014-12-12 15:58:26 -0800571 }
572}
573
574static void freefield(upb_refcounted *r) {
575 upb_fielddef *f = (upb_fielddef*)r;
576 upb_fielddef_uninit_default(f);
577 if (f->subdef_is_symbolic)
578 free(f->sub.name);
Josh Habermane8ed0212015-06-08 17:56:03 -0700579 upb_def_uninit(upb_fielddef_upcast_mutable(f));
Chris Fallin91473dc2014-12-12 15:58:26 -0800580 free(f);
581}
582
583static const char *enumdefaultstr(const upb_fielddef *f) {
Josh Habermane8ed0212015-06-08 17:56:03 -0700584 const upb_enumdef *e;
Chris Fallin91473dc2014-12-12 15:58:26 -0800585 assert(f->type_is_set_ && f->type_ == UPB_TYPE_ENUM);
Josh Habermane8ed0212015-06-08 17:56:03 -0700586 e = upb_fielddef_enumsubdef(f);
Chris Fallin91473dc2014-12-12 15:58:26 -0800587 if (f->default_is_string && f->defaultval.bytes) {
Josh Habermane8ed0212015-06-08 17:56:03 -0700588 /* Default was explicitly set as a string. */
Chris Fallin91473dc2014-12-12 15:58:26 -0800589 str_t *s = f->defaultval.bytes;
590 return s->str;
591 } else if (e) {
592 if (!f->default_is_string) {
Josh Habermane8ed0212015-06-08 17:56:03 -0700593 /* Default was explicitly set as an integer; look it up in enumdef. */
Chris Fallin91473dc2014-12-12 15:58:26 -0800594 const char *name = upb_enumdef_iton(e, f->defaultval.sint);
595 if (name) {
596 return name;
597 }
598 } else {
Josh Habermane8ed0212015-06-08 17:56:03 -0700599 /* Default is completely unset; pull enumdef default. */
Chris Fallin91473dc2014-12-12 15:58:26 -0800600 if (upb_enumdef_numvals(e) > 0) {
601 const char *name = upb_enumdef_iton(e, upb_enumdef_default(e));
602 assert(name);
603 return name;
604 }
605 }
606 }
607 return NULL;
608}
609
610static bool enumdefaultint32(const upb_fielddef *f, int32_t *val) {
Josh Habermane8ed0212015-06-08 17:56:03 -0700611 const upb_enumdef *e;
Chris Fallin91473dc2014-12-12 15:58:26 -0800612 assert(f->type_is_set_ && f->type_ == UPB_TYPE_ENUM);
Josh Habermane8ed0212015-06-08 17:56:03 -0700613 e = upb_fielddef_enumsubdef(f);
Chris Fallin91473dc2014-12-12 15:58:26 -0800614 if (!f->default_is_string) {
Josh Habermane8ed0212015-06-08 17:56:03 -0700615 /* Default was explicitly set as an integer. */
Chris Fallin91473dc2014-12-12 15:58:26 -0800616 *val = f->defaultval.sint;
617 return true;
618 } else if (e) {
619 if (f->defaultval.bytes) {
Josh Habermane8ed0212015-06-08 17:56:03 -0700620 /* Default was explicitly set as a str; try to lookup corresponding int. */
Chris Fallin91473dc2014-12-12 15:58:26 -0800621 str_t *s = f->defaultval.bytes;
622 if (upb_enumdef_ntoiz(e, s->str, val)) {
623 return true;
624 }
625 } else {
Josh Habermane8ed0212015-06-08 17:56:03 -0700626 /* Default is unset; try to pull in enumdef default. */
Chris Fallin91473dc2014-12-12 15:58:26 -0800627 if (upb_enumdef_numvals(e) > 0) {
628 *val = upb_enumdef_default(e);
629 return true;
630 }
631 }
632 }
633 return false;
634}
635
Josh Habermane8ed0212015-06-08 17:56:03 -0700636upb_fielddef *upb_fielddef_new(const void *o) {
Chris Fallin91473dc2014-12-12 15:58:26 -0800637 static const struct upb_refcounted_vtbl vtbl = {visitfield, freefield};
638 upb_fielddef *f = malloc(sizeof(*f));
639 if (!f) return NULL;
Josh Habermane8ed0212015-06-08 17:56:03 -0700640 if (!upb_def_init(upb_fielddef_upcast_mutable(f), UPB_DEF_FIELD, &vtbl, o)) {
Chris Fallin91473dc2014-12-12 15:58:26 -0800641 free(f);
642 return NULL;
643 }
644 f->msg.def = NULL;
645 f->sub.def = NULL;
Chris Fallinfcd88892015-01-13 18:14:39 -0800646 f->oneof = NULL;
Chris Fallin91473dc2014-12-12 15:58:26 -0800647 f->subdef_is_symbolic = false;
648 f->msg_is_symbolic = false;
649 f->label_ = UPB_LABEL_OPTIONAL;
650 f->type_ = UPB_TYPE_INT32;
651 f->number_ = 0;
652 f->type_is_set_ = false;
653 f->tagdelim = false;
654 f->is_extension_ = false;
655 f->lazy_ = false;
656 f->packed_ = true;
657
Josh Habermane8ed0212015-06-08 17:56:03 -0700658 /* For the moment we default this to UPB_INTFMT_VARIABLE, since it will work
659 * with all integer types and is in some since more "default" since the most
660 * normal-looking proto2 types int32/int64/uint32/uint64 use variable.
661 *
662 * Other options to consider:
663 * - there is no default; users must set this manually (like type).
664 * - default signed integers to UPB_INTFMT_ZIGZAG, since it's more likely to
665 * be an optimal default for signed integers. */
Chris Fallin91473dc2014-12-12 15:58:26 -0800666 f->intfmt = UPB_INTFMT_VARIABLE;
667 return f;
668}
669
670upb_fielddef *upb_fielddef_dup(const upb_fielddef *f, const void *owner) {
Josh Habermane8ed0212015-06-08 17:56:03 -0700671 const char *srcname;
Chris Fallin91473dc2014-12-12 15:58:26 -0800672 upb_fielddef *newf = upb_fielddef_new(owner);
673 if (!newf) return NULL;
674 upb_fielddef_settype(newf, upb_fielddef_type(f));
675 upb_fielddef_setlabel(newf, upb_fielddef_label(f));
676 upb_fielddef_setnumber(newf, upb_fielddef_number(f), NULL);
677 upb_fielddef_setname(newf, upb_fielddef_name(f), NULL);
678 if (f->default_is_string && f->defaultval.bytes) {
679 str_t *s = f->defaultval.bytes;
680 upb_fielddef_setdefaultstr(newf, s->str, s->len, NULL);
681 } else {
682 newf->default_is_string = f->default_is_string;
683 newf->defaultval = f->defaultval;
684 }
685
Chris Fallin91473dc2014-12-12 15:58:26 -0800686 if (f->subdef_is_symbolic) {
Josh Habermane8ed0212015-06-08 17:56:03 -0700687 srcname = f->sub.name; /* Might be NULL. */
Chris Fallin91473dc2014-12-12 15:58:26 -0800688 } else {
689 srcname = f->sub.def ? upb_def_fullname(f->sub.def) : NULL;
690 }
691 if (srcname) {
692 char *newname = malloc(strlen(f->sub.def->fullname) + 2);
693 if (!newname) {
694 upb_fielddef_unref(newf, owner);
695 return NULL;
696 }
697 strcpy(newname, ".");
698 strcat(newname, f->sub.def->fullname);
699 upb_fielddef_setsubdefname(newf, newname, NULL);
700 free(newname);
701 }
702
703 return newf;
704}
705
Chris Fallin91473dc2014-12-12 15:58:26 -0800706bool upb_fielddef_typeisset(const upb_fielddef *f) {
707 return f->type_is_set_;
708}
709
710upb_fieldtype_t upb_fielddef_type(const upb_fielddef *f) {
711 assert(f->type_is_set_);
712 return f->type_;
713}
714
715uint32_t upb_fielddef_index(const upb_fielddef *f) {
716 return f->index_;
717}
718
719upb_label_t upb_fielddef_label(const upb_fielddef *f) {
720 return f->label_;
721}
722
723upb_intfmt_t upb_fielddef_intfmt(const upb_fielddef *f) {
724 return f->intfmt;
725}
726
727bool upb_fielddef_istagdelim(const upb_fielddef *f) {
728 return f->tagdelim;
729}
730
731uint32_t upb_fielddef_number(const upb_fielddef *f) {
732 return f->number_;
733}
734
735bool upb_fielddef_isextension(const upb_fielddef *f) {
736 return f->is_extension_;
737}
738
739bool upb_fielddef_lazy(const upb_fielddef *f) {
740 return f->lazy_;
741}
742
743bool upb_fielddef_packed(const upb_fielddef *f) {
744 return f->packed_;
745}
746
747const char *upb_fielddef_name(const upb_fielddef *f) {
Josh Habermane8ed0212015-06-08 17:56:03 -0700748 return upb_def_fullname(upb_fielddef_upcast(f));
Chris Fallin91473dc2014-12-12 15:58:26 -0800749}
750
Josh Habermanf654d492016-02-18 11:07:51 -0800751size_t upb_fielddef_getjsonname(const upb_fielddef *f, char *buf, size_t len) {
Josh Haberman78da6662016-01-13 19:05:43 -0800752 const char *name = upb_fielddef_name(f);
Josh Habermanf654d492016-02-18 11:07:51 -0800753 size_t src, dst = 0;
Josh Haberman78da6662016-01-13 19:05:43 -0800754 bool ucase_next = false;
755
Josh Habermanf654d492016-02-18 11:07:51 -0800756#define WRITE(byte) \
757 ++dst; \
758 if (dst < len) buf[dst - 1] = byte; \
759 else if (dst == len) buf[dst - 1] = '\0'
760
761 if (!name) {
762 WRITE('\0');
763 return 0;
764 }
Josh Haberman78da6662016-01-13 19:05:43 -0800765
766 /* Implement the transformation as described in the spec:
767 * 1. upper case all letters after an underscore.
768 * 2. remove all underscores.
769 */
Josh Habermanf654d492016-02-18 11:07:51 -0800770 for (src = 0; name[src]; src++) {
771 if (name[src] == '_') {
Josh Haberman78da6662016-01-13 19:05:43 -0800772 ucase_next = true;
773 continue;
774 }
775
776 if (ucase_next) {
Josh Habermanf654d492016-02-18 11:07:51 -0800777 WRITE(toupper(name[src]));
Josh Haberman78da6662016-01-13 19:05:43 -0800778 ucase_next = false;
779 } else {
Josh Habermanf654d492016-02-18 11:07:51 -0800780 WRITE(name[src]);
Josh Haberman78da6662016-01-13 19:05:43 -0800781 }
782 }
783
Josh Habermanf654d492016-02-18 11:07:51 -0800784 WRITE('\0');
785 return dst;
786
787#undef WRITE
Josh Haberman78da6662016-01-13 19:05:43 -0800788}
789
Chris Fallin91473dc2014-12-12 15:58:26 -0800790const upb_msgdef *upb_fielddef_containingtype(const upb_fielddef *f) {
791 return f->msg_is_symbolic ? NULL : f->msg.def;
792}
793
Chris Fallinfcd88892015-01-13 18:14:39 -0800794const upb_oneofdef *upb_fielddef_containingoneof(const upb_fielddef *f) {
795 return f->oneof;
796}
797
Chris Fallin91473dc2014-12-12 15:58:26 -0800798upb_msgdef *upb_fielddef_containingtype_mutable(upb_fielddef *f) {
799 return (upb_msgdef*)upb_fielddef_containingtype(f);
800}
801
802const char *upb_fielddef_containingtypename(upb_fielddef *f) {
803 return f->msg_is_symbolic ? f->msg.name : NULL;
804}
805
806static void release_containingtype(upb_fielddef *f) {
807 if (f->msg_is_symbolic) free(f->msg.name);
808}
809
810bool upb_fielddef_setcontainingtypename(upb_fielddef *f, const char *name,
811 upb_status *s) {
812 assert(!upb_fielddef_isfrozen(f));
813 if (upb_fielddef_containingtype(f)) {
814 upb_status_seterrmsg(s, "field has already been added to a message.");
815 return false;
816 }
Josh Habermane8ed0212015-06-08 17:56:03 -0700817 /* TODO: validate name (upb_isident() doesn't quite work atm because this name
818 * may have a leading "."). */
Chris Fallin91473dc2014-12-12 15:58:26 -0800819 release_containingtype(f);
820 f->msg.name = upb_strdup(name);
821 f->msg_is_symbolic = true;
822 return true;
823}
824
825bool upb_fielddef_setname(upb_fielddef *f, const char *name, upb_status *s) {
Chris Fallinfcd88892015-01-13 18:14:39 -0800826 if (upb_fielddef_containingtype(f) || upb_fielddef_containingoneof(f)) {
827 upb_status_seterrmsg(s, "Already added to message or oneof");
828 return false;
829 }
Josh Habermane8ed0212015-06-08 17:56:03 -0700830 return upb_def_setfullname(upb_fielddef_upcast_mutable(f), name, s);
Chris Fallin91473dc2014-12-12 15:58:26 -0800831}
832
833static void chkdefaulttype(const upb_fielddef *f, upb_fieldtype_t type) {
834 UPB_UNUSED(f);
835 UPB_UNUSED(type);
836 assert(f->type_is_set_ && upb_fielddef_type(f) == type);
837}
838
839int64_t upb_fielddef_defaultint64(const upb_fielddef *f) {
840 chkdefaulttype(f, UPB_TYPE_INT64);
841 return f->defaultval.sint;
842}
843
844int32_t upb_fielddef_defaultint32(const upb_fielddef *f) {
845 if (f->type_is_set_ && upb_fielddef_type(f) == UPB_TYPE_ENUM) {
846 int32_t val;
847 bool ok = enumdefaultint32(f, &val);
848 UPB_ASSERT_VAR(ok, ok);
849 return val;
850 } else {
851 chkdefaulttype(f, UPB_TYPE_INT32);
852 return f->defaultval.sint;
853 }
854}
855
856uint64_t upb_fielddef_defaultuint64(const upb_fielddef *f) {
857 chkdefaulttype(f, UPB_TYPE_UINT64);
858 return f->defaultval.uint;
859}
860
861uint32_t upb_fielddef_defaultuint32(const upb_fielddef *f) {
862 chkdefaulttype(f, UPB_TYPE_UINT32);
863 return f->defaultval.uint;
864}
865
866bool upb_fielddef_defaultbool(const upb_fielddef *f) {
867 chkdefaulttype(f, UPB_TYPE_BOOL);
868 return f->defaultval.uint;
869}
870
871float upb_fielddef_defaultfloat(const upb_fielddef *f) {
872 chkdefaulttype(f, UPB_TYPE_FLOAT);
873 return f->defaultval.flt;
874}
875
876double upb_fielddef_defaultdouble(const upb_fielddef *f) {
877 chkdefaulttype(f, UPB_TYPE_DOUBLE);
878 return f->defaultval.dbl;
879}
880
881const char *upb_fielddef_defaultstr(const upb_fielddef *f, size_t *len) {
882 assert(f->type_is_set_);
883 assert(upb_fielddef_type(f) == UPB_TYPE_STRING ||
884 upb_fielddef_type(f) == UPB_TYPE_BYTES ||
885 upb_fielddef_type(f) == UPB_TYPE_ENUM);
886
887 if (upb_fielddef_type(f) == UPB_TYPE_ENUM) {
888 const char *ret = enumdefaultstr(f);
889 assert(ret);
Josh Habermane8ed0212015-06-08 17:56:03 -0700890 /* Enum defaults can't have embedded NULLs. */
Chris Fallin91473dc2014-12-12 15:58:26 -0800891 if (len) *len = strlen(ret);
892 return ret;
893 }
894
895 if (f->default_is_string) {
896 str_t *str = f->defaultval.bytes;
897 if (len) *len = str->len;
898 return str->str;
899 }
900
901 return NULL;
902}
903
904static void upb_fielddef_init_default(upb_fielddef *f) {
905 f->default_is_string = false;
906 switch (upb_fielddef_type(f)) {
907 case UPB_TYPE_DOUBLE: f->defaultval.dbl = 0; break;
908 case UPB_TYPE_FLOAT: f->defaultval.flt = 0; break;
909 case UPB_TYPE_INT32:
910 case UPB_TYPE_INT64: f->defaultval.sint = 0; break;
911 case UPB_TYPE_UINT64:
912 case UPB_TYPE_UINT32:
913 case UPB_TYPE_BOOL: f->defaultval.uint = 0; break;
914 case UPB_TYPE_STRING:
915 case UPB_TYPE_BYTES:
916 f->defaultval.bytes = newstr("", 0);
917 f->default_is_string = true;
918 break;
919 case UPB_TYPE_MESSAGE: break;
920 case UPB_TYPE_ENUM:
Josh Habermane8ed0212015-06-08 17:56:03 -0700921 /* This is our special sentinel that indicates "not set" for an enum. */
Chris Fallin91473dc2014-12-12 15:58:26 -0800922 f->default_is_string = true;
923 f->defaultval.bytes = NULL;
924 break;
925 }
926}
927
928const upb_def *upb_fielddef_subdef(const upb_fielddef *f) {
929 return f->subdef_is_symbolic ? NULL : f->sub.def;
930}
931
932const upb_msgdef *upb_fielddef_msgsubdef(const upb_fielddef *f) {
933 const upb_def *def = upb_fielddef_subdef(f);
934 return def ? upb_dyncast_msgdef(def) : NULL;
935}
936
937const upb_enumdef *upb_fielddef_enumsubdef(const upb_fielddef *f) {
938 const upb_def *def = upb_fielddef_subdef(f);
939 return def ? upb_dyncast_enumdef(def) : NULL;
940}
941
942upb_def *upb_fielddef_subdef_mutable(upb_fielddef *f) {
943 return (upb_def*)upb_fielddef_subdef(f);
944}
945
946const char *upb_fielddef_subdefname(const upb_fielddef *f) {
947 if (f->subdef_is_symbolic) {
948 return f->sub.name;
949 } else if (f->sub.def) {
950 return upb_def_fullname(f->sub.def);
951 } else {
952 return NULL;
953 }
954}
955
956bool upb_fielddef_setnumber(upb_fielddef *f, uint32_t number, upb_status *s) {
957 if (upb_fielddef_containingtype(f)) {
958 upb_status_seterrmsg(
959 s, "cannot change field number after adding to a message");
960 return false;
961 }
962 if (number == 0 || number > UPB_MAX_FIELDNUMBER) {
963 upb_status_seterrf(s, "invalid field number (%u)", number);
964 return false;
965 }
966 f->number_ = number;
967 return true;
968}
969
970void upb_fielddef_settype(upb_fielddef *f, upb_fieldtype_t type) {
971 assert(!upb_fielddef_isfrozen(f));
972 assert(upb_fielddef_checktype(type));
973 upb_fielddef_uninit_default(f);
974 f->type_ = type;
975 f->type_is_set_ = true;
976 upb_fielddef_init_default(f);
977}
978
979void upb_fielddef_setdescriptortype(upb_fielddef *f, int type) {
980 assert(!upb_fielddef_isfrozen(f));
981 switch (type) {
982 case UPB_DESCRIPTOR_TYPE_DOUBLE:
983 upb_fielddef_settype(f, UPB_TYPE_DOUBLE);
984 break;
985 case UPB_DESCRIPTOR_TYPE_FLOAT:
986 upb_fielddef_settype(f, UPB_TYPE_FLOAT);
987 break;
988 case UPB_DESCRIPTOR_TYPE_INT64:
989 case UPB_DESCRIPTOR_TYPE_SFIXED64:
990 case UPB_DESCRIPTOR_TYPE_SINT64:
991 upb_fielddef_settype(f, UPB_TYPE_INT64);
992 break;
993 case UPB_DESCRIPTOR_TYPE_UINT64:
994 case UPB_DESCRIPTOR_TYPE_FIXED64:
995 upb_fielddef_settype(f, UPB_TYPE_UINT64);
996 break;
997 case UPB_DESCRIPTOR_TYPE_INT32:
998 case UPB_DESCRIPTOR_TYPE_SFIXED32:
999 case UPB_DESCRIPTOR_TYPE_SINT32:
1000 upb_fielddef_settype(f, UPB_TYPE_INT32);
1001 break;
1002 case UPB_DESCRIPTOR_TYPE_UINT32:
1003 case UPB_DESCRIPTOR_TYPE_FIXED32:
1004 upb_fielddef_settype(f, UPB_TYPE_UINT32);
1005 break;
1006 case UPB_DESCRIPTOR_TYPE_BOOL:
1007 upb_fielddef_settype(f, UPB_TYPE_BOOL);
1008 break;
1009 case UPB_DESCRIPTOR_TYPE_STRING:
1010 upb_fielddef_settype(f, UPB_TYPE_STRING);
1011 break;
1012 case UPB_DESCRIPTOR_TYPE_BYTES:
1013 upb_fielddef_settype(f, UPB_TYPE_BYTES);
1014 break;
1015 case UPB_DESCRIPTOR_TYPE_GROUP:
1016 case UPB_DESCRIPTOR_TYPE_MESSAGE:
1017 upb_fielddef_settype(f, UPB_TYPE_MESSAGE);
1018 break;
1019 case UPB_DESCRIPTOR_TYPE_ENUM:
1020 upb_fielddef_settype(f, UPB_TYPE_ENUM);
1021 break;
1022 default: assert(false);
1023 }
1024
1025 if (type == UPB_DESCRIPTOR_TYPE_FIXED64 ||
1026 type == UPB_DESCRIPTOR_TYPE_FIXED32 ||
1027 type == UPB_DESCRIPTOR_TYPE_SFIXED64 ||
1028 type == UPB_DESCRIPTOR_TYPE_SFIXED32) {
1029 upb_fielddef_setintfmt(f, UPB_INTFMT_FIXED);
1030 } else if (type == UPB_DESCRIPTOR_TYPE_SINT64 ||
1031 type == UPB_DESCRIPTOR_TYPE_SINT32) {
1032 upb_fielddef_setintfmt(f, UPB_INTFMT_ZIGZAG);
1033 } else {
1034 upb_fielddef_setintfmt(f, UPB_INTFMT_VARIABLE);
1035 }
1036
1037 upb_fielddef_settagdelim(f, type == UPB_DESCRIPTOR_TYPE_GROUP);
1038}
1039
1040upb_descriptortype_t upb_fielddef_descriptortype(const upb_fielddef *f) {
1041 switch (upb_fielddef_type(f)) {
1042 case UPB_TYPE_FLOAT: return UPB_DESCRIPTOR_TYPE_FLOAT;
1043 case UPB_TYPE_DOUBLE: return UPB_DESCRIPTOR_TYPE_DOUBLE;
1044 case UPB_TYPE_BOOL: return UPB_DESCRIPTOR_TYPE_BOOL;
1045 case UPB_TYPE_STRING: return UPB_DESCRIPTOR_TYPE_STRING;
1046 case UPB_TYPE_BYTES: return UPB_DESCRIPTOR_TYPE_BYTES;
1047 case UPB_TYPE_ENUM: return UPB_DESCRIPTOR_TYPE_ENUM;
1048 case UPB_TYPE_INT32:
1049 switch (upb_fielddef_intfmt(f)) {
1050 case UPB_INTFMT_VARIABLE: return UPB_DESCRIPTOR_TYPE_INT32;
1051 case UPB_INTFMT_FIXED: return UPB_DESCRIPTOR_TYPE_SFIXED32;
1052 case UPB_INTFMT_ZIGZAG: return UPB_DESCRIPTOR_TYPE_SINT32;
1053 }
1054 case UPB_TYPE_INT64:
1055 switch (upb_fielddef_intfmt(f)) {
1056 case UPB_INTFMT_VARIABLE: return UPB_DESCRIPTOR_TYPE_INT64;
1057 case UPB_INTFMT_FIXED: return UPB_DESCRIPTOR_TYPE_SFIXED64;
1058 case UPB_INTFMT_ZIGZAG: return UPB_DESCRIPTOR_TYPE_SINT64;
1059 }
1060 case UPB_TYPE_UINT32:
1061 switch (upb_fielddef_intfmt(f)) {
1062 case UPB_INTFMT_VARIABLE: return UPB_DESCRIPTOR_TYPE_UINT32;
1063 case UPB_INTFMT_FIXED: return UPB_DESCRIPTOR_TYPE_FIXED32;
1064 case UPB_INTFMT_ZIGZAG: return -1;
1065 }
1066 case UPB_TYPE_UINT64:
1067 switch (upb_fielddef_intfmt(f)) {
1068 case UPB_INTFMT_VARIABLE: return UPB_DESCRIPTOR_TYPE_UINT64;
1069 case UPB_INTFMT_FIXED: return UPB_DESCRIPTOR_TYPE_FIXED64;
1070 case UPB_INTFMT_ZIGZAG: return -1;
1071 }
1072 case UPB_TYPE_MESSAGE:
1073 return upb_fielddef_istagdelim(f) ?
1074 UPB_DESCRIPTOR_TYPE_GROUP : UPB_DESCRIPTOR_TYPE_MESSAGE;
1075 }
1076 return 0;
1077}
1078
1079void upb_fielddef_setisextension(upb_fielddef *f, bool is_extension) {
1080 assert(!upb_fielddef_isfrozen(f));
1081 f->is_extension_ = is_extension;
1082}
1083
1084void upb_fielddef_setlazy(upb_fielddef *f, bool lazy) {
1085 assert(!upb_fielddef_isfrozen(f));
1086 f->lazy_ = lazy;
1087}
1088
1089void upb_fielddef_setpacked(upb_fielddef *f, bool packed) {
1090 assert(!upb_fielddef_isfrozen(f));
1091 f->packed_ = packed;
1092}
1093
1094void upb_fielddef_setlabel(upb_fielddef *f, upb_label_t label) {
1095 assert(!upb_fielddef_isfrozen(f));
1096 assert(upb_fielddef_checklabel(label));
1097 f->label_ = label;
1098}
1099
1100void upb_fielddef_setintfmt(upb_fielddef *f, upb_intfmt_t fmt) {
1101 assert(!upb_fielddef_isfrozen(f));
1102 assert(upb_fielddef_checkintfmt(fmt));
1103 f->intfmt = fmt;
1104}
1105
1106void upb_fielddef_settagdelim(upb_fielddef *f, bool tag_delim) {
1107 assert(!upb_fielddef_isfrozen(f));
1108 f->tagdelim = tag_delim;
1109 f->tagdelim = tag_delim;
1110}
1111
1112static bool checksetdefault(upb_fielddef *f, upb_fieldtype_t type) {
1113 if (!f->type_is_set_ || upb_fielddef_isfrozen(f) ||
1114 upb_fielddef_type(f) != type) {
1115 assert(false);
1116 return false;
1117 }
1118 if (f->default_is_string) {
1119 str_t *s = f->defaultval.bytes;
1120 assert(s || type == UPB_TYPE_ENUM);
1121 if (s) freestr(s);
1122 }
1123 f->default_is_string = false;
1124 return true;
1125}
1126
1127void upb_fielddef_setdefaultint64(upb_fielddef *f, int64_t value) {
1128 if (checksetdefault(f, UPB_TYPE_INT64))
1129 f->defaultval.sint = value;
1130}
1131
1132void upb_fielddef_setdefaultint32(upb_fielddef *f, int32_t value) {
1133 if ((upb_fielddef_type(f) == UPB_TYPE_ENUM &&
1134 checksetdefault(f, UPB_TYPE_ENUM)) ||
1135 checksetdefault(f, UPB_TYPE_INT32)) {
1136 f->defaultval.sint = value;
1137 }
1138}
1139
1140void upb_fielddef_setdefaultuint64(upb_fielddef *f, uint64_t value) {
1141 if (checksetdefault(f, UPB_TYPE_UINT64))
1142 f->defaultval.uint = value;
1143}
1144
1145void upb_fielddef_setdefaultuint32(upb_fielddef *f, uint32_t value) {
1146 if (checksetdefault(f, UPB_TYPE_UINT32))
1147 f->defaultval.uint = value;
1148}
1149
1150void upb_fielddef_setdefaultbool(upb_fielddef *f, bool value) {
1151 if (checksetdefault(f, UPB_TYPE_BOOL))
1152 f->defaultval.uint = value;
1153}
1154
1155void upb_fielddef_setdefaultfloat(upb_fielddef *f, float value) {
1156 if (checksetdefault(f, UPB_TYPE_FLOAT))
1157 f->defaultval.flt = value;
1158}
1159
1160void upb_fielddef_setdefaultdouble(upb_fielddef *f, double value) {
1161 if (checksetdefault(f, UPB_TYPE_DOUBLE))
1162 f->defaultval.dbl = value;
1163}
1164
1165bool upb_fielddef_setdefaultstr(upb_fielddef *f, const void *str, size_t len,
1166 upb_status *s) {
Josh Habermane8ed0212015-06-08 17:56:03 -07001167 str_t *str2;
Chris Fallin91473dc2014-12-12 15:58:26 -08001168 assert(upb_fielddef_isstring(f) || f->type_ == UPB_TYPE_ENUM);
1169 if (f->type_ == UPB_TYPE_ENUM && !upb_isident(str, len, false, s))
1170 return false;
1171
1172 if (f->default_is_string) {
1173 str_t *s = f->defaultval.bytes;
1174 assert(s || f->type_ == UPB_TYPE_ENUM);
1175 if (s) freestr(s);
1176 } else {
1177 assert(f->type_ == UPB_TYPE_ENUM);
1178 }
1179
Josh Habermane8ed0212015-06-08 17:56:03 -07001180 str2 = newstr(str, len);
Chris Fallin91473dc2014-12-12 15:58:26 -08001181 f->defaultval.bytes = str2;
1182 f->default_is_string = true;
1183 return true;
1184}
1185
1186void upb_fielddef_setdefaultcstr(upb_fielddef *f, const char *str,
1187 upb_status *s) {
1188 assert(f->type_is_set_);
1189 upb_fielddef_setdefaultstr(f, str, str ? strlen(str) : 0, s);
1190}
1191
1192bool upb_fielddef_enumhasdefaultint32(const upb_fielddef *f) {
Chris Fallin91473dc2014-12-12 15:58:26 -08001193 int32_t val;
Josh Habermane8ed0212015-06-08 17:56:03 -07001194 assert(f->type_is_set_ && f->type_ == UPB_TYPE_ENUM);
Chris Fallin91473dc2014-12-12 15:58:26 -08001195 return enumdefaultint32(f, &val);
1196}
1197
1198bool upb_fielddef_enumhasdefaultstr(const upb_fielddef *f) {
1199 assert(f->type_is_set_ && f->type_ == UPB_TYPE_ENUM);
1200 return enumdefaultstr(f) != NULL;
1201}
1202
1203static bool upb_subdef_typecheck(upb_fielddef *f, const upb_def *subdef,
1204 upb_status *s) {
1205 if (f->type_ == UPB_TYPE_MESSAGE) {
1206 if (upb_dyncast_msgdef(subdef)) return true;
1207 upb_status_seterrmsg(s, "invalid subdef type for this submessage field");
1208 return false;
1209 } else if (f->type_ == UPB_TYPE_ENUM) {
1210 if (upb_dyncast_enumdef(subdef)) return true;
1211 upb_status_seterrmsg(s, "invalid subdef type for this enum field");
1212 return false;
1213 } else {
1214 upb_status_seterrmsg(s, "only message and enum fields can have a subdef");
1215 return false;
1216 }
1217}
1218
1219static void release_subdef(upb_fielddef *f) {
1220 if (f->subdef_is_symbolic) {
1221 free(f->sub.name);
1222 } else if (f->sub.def) {
1223 upb_unref2(f->sub.def, f);
1224 }
1225}
1226
1227bool upb_fielddef_setsubdef(upb_fielddef *f, const upb_def *subdef,
1228 upb_status *s) {
1229 assert(!upb_fielddef_isfrozen(f));
1230 assert(upb_fielddef_hassubdef(f));
1231 if (subdef && !upb_subdef_typecheck(f, subdef, s)) return false;
1232 release_subdef(f);
1233 f->sub.def = subdef;
1234 f->subdef_is_symbolic = false;
1235 if (f->sub.def) upb_ref2(f->sub.def, f);
1236 return true;
1237}
1238
1239bool upb_fielddef_setmsgsubdef(upb_fielddef *f, const upb_msgdef *subdef,
1240 upb_status *s) {
Josh Habermane8ed0212015-06-08 17:56:03 -07001241 return upb_fielddef_setsubdef(f, upb_msgdef_upcast(subdef), s);
Chris Fallin91473dc2014-12-12 15:58:26 -08001242}
1243
1244bool upb_fielddef_setenumsubdef(upb_fielddef *f, const upb_enumdef *subdef,
1245 upb_status *s) {
Josh Habermane8ed0212015-06-08 17:56:03 -07001246 return upb_fielddef_setsubdef(f, upb_enumdef_upcast(subdef), s);
Chris Fallin91473dc2014-12-12 15:58:26 -08001247}
1248
1249bool upb_fielddef_setsubdefname(upb_fielddef *f, const char *name,
1250 upb_status *s) {
1251 assert(!upb_fielddef_isfrozen(f));
1252 if (!upb_fielddef_hassubdef(f)) {
1253 upb_status_seterrmsg(s, "field type does not accept a subdef");
1254 return false;
1255 }
Josh Habermane8ed0212015-06-08 17:56:03 -07001256 /* TODO: validate name (upb_isident() doesn't quite work atm because this name
1257 * may have a leading "."). */
Chris Fallin91473dc2014-12-12 15:58:26 -08001258 release_subdef(f);
1259 f->sub.name = upb_strdup(name);
1260 f->subdef_is_symbolic = true;
1261 return true;
1262}
1263
1264bool upb_fielddef_issubmsg(const upb_fielddef *f) {
1265 return upb_fielddef_type(f) == UPB_TYPE_MESSAGE;
1266}
1267
1268bool upb_fielddef_isstring(const upb_fielddef *f) {
1269 return upb_fielddef_type(f) == UPB_TYPE_STRING ||
1270 upb_fielddef_type(f) == UPB_TYPE_BYTES;
1271}
1272
1273bool upb_fielddef_isseq(const upb_fielddef *f) {
1274 return upb_fielddef_label(f) == UPB_LABEL_REPEATED;
1275}
1276
1277bool upb_fielddef_isprimitive(const upb_fielddef *f) {
1278 return !upb_fielddef_isstring(f) && !upb_fielddef_issubmsg(f);
1279}
1280
Chris Fallina5075922015-02-02 15:07:34 -08001281bool upb_fielddef_ismap(const upb_fielddef *f) {
1282 return upb_fielddef_isseq(f) && upb_fielddef_issubmsg(f) &&
1283 upb_msgdef_mapentry(upb_fielddef_msgsubdef(f));
1284}
1285
Josh Haberman78da6662016-01-13 19:05:43 -08001286bool upb_fielddef_haspresence(const upb_fielddef *f) {
1287 if (upb_fielddef_isseq(f)) return false;
1288 if (upb_fielddef_issubmsg(f)) return true;
1289
1290 /* Primitive field: return true unless there is a message that specifies
1291 * presence should not exist. */
1292 if (f->msg_is_symbolic || !f->msg.def) return true;
Josh Haberman94e54b32016-04-14 12:06:09 -07001293 return f->msg.def->syntax == UPB_SYNTAX_PROTO2;
Josh Haberman78da6662016-01-13 19:05:43 -08001294}
1295
Chris Fallin91473dc2014-12-12 15:58:26 -08001296bool upb_fielddef_hassubdef(const upb_fielddef *f) {
1297 return upb_fielddef_issubmsg(f) || upb_fielddef_type(f) == UPB_TYPE_ENUM;
1298}
1299
1300static bool between(int32_t x, int32_t low, int32_t high) {
1301 return x >= low && x <= high;
1302}
1303
1304bool upb_fielddef_checklabel(int32_t label) { return between(label, 1, 3); }
1305bool upb_fielddef_checktype(int32_t type) { return between(type, 1, 11); }
1306bool upb_fielddef_checkintfmt(int32_t fmt) { return between(fmt, 1, 3); }
1307
1308bool upb_fielddef_checkdescriptortype(int32_t type) {
1309 return between(type, 1, 18);
1310}
1311
1312/* upb_msgdef *****************************************************************/
1313
1314static void visitmsg(const upb_refcounted *r, upb_refcounted_visit *visit,
1315 void *closure) {
Josh Habermane8ed0212015-06-08 17:56:03 -07001316 upb_msg_oneof_iter o;
Chris Fallin91473dc2014-12-12 15:58:26 -08001317 const upb_msgdef *m = (const upb_msgdef*)r;
Chris Fallinfcd88892015-01-13 18:14:39 -08001318 upb_msg_field_iter i;
1319 for(upb_msg_field_begin(&i, m);
1320 !upb_msg_field_done(&i);
1321 upb_msg_field_next(&i)) {
Chris Fallin91473dc2014-12-12 15:58:26 -08001322 upb_fielddef *f = upb_msg_iter_field(&i);
Josh Habermane8ed0212015-06-08 17:56:03 -07001323 visit(r, upb_fielddef_upcast2(f), closure);
Chris Fallin91473dc2014-12-12 15:58:26 -08001324 }
Chris Fallinfcd88892015-01-13 18:14:39 -08001325 for(upb_msg_oneof_begin(&o, m);
1326 !upb_msg_oneof_done(&o);
1327 upb_msg_oneof_next(&o)) {
1328 upb_oneofdef *f = upb_msg_iter_oneof(&o);
Josh Haberman94e54b32016-04-14 12:06:09 -07001329 visit(r, upb_oneofdef_upcast(f), closure);
Chris Fallinfcd88892015-01-13 18:14:39 -08001330 }
Chris Fallin91473dc2014-12-12 15:58:26 -08001331}
1332
1333static void freemsg(upb_refcounted *r) {
1334 upb_msgdef *m = (upb_msgdef*)r;
Chris Fallinfcd88892015-01-13 18:14:39 -08001335 upb_strtable_uninit(&m->ntoo);
Chris Fallin91473dc2014-12-12 15:58:26 -08001336 upb_strtable_uninit(&m->ntof);
1337 upb_inttable_uninit(&m->itof);
Josh Habermane8ed0212015-06-08 17:56:03 -07001338 upb_def_uninit(upb_msgdef_upcast_mutable(m));
Chris Fallin91473dc2014-12-12 15:58:26 -08001339 free(m);
1340}
1341
1342upb_msgdef *upb_msgdef_new(const void *owner) {
1343 static const struct upb_refcounted_vtbl vtbl = {visitmsg, freemsg};
1344 upb_msgdef *m = malloc(sizeof(*m));
1345 if (!m) return NULL;
Josh Habermane8ed0212015-06-08 17:56:03 -07001346 if (!upb_def_init(upb_msgdef_upcast_mutable(m), UPB_DEF_MSG, &vtbl, owner))
1347 goto err2;
Chris Fallinfcd88892015-01-13 18:14:39 -08001348 if (!upb_inttable_init(&m->itof, UPB_CTYPE_PTR)) goto err3;
1349 if (!upb_strtable_init(&m->ntof, UPB_CTYPE_PTR)) goto err2;
1350 if (!upb_strtable_init(&m->ntoo, UPB_CTYPE_PTR)) goto err1;
Chris Fallinfd1a3ff2015-01-06 15:44:09 -08001351 m->map_entry = false;
Josh Haberman94e54b32016-04-14 12:06:09 -07001352 m->syntax = UPB_SYNTAX_PROTO2;
Chris Fallin91473dc2014-12-12 15:58:26 -08001353 return m;
1354
1355err1:
Chris Fallinfcd88892015-01-13 18:14:39 -08001356 upb_strtable_uninit(&m->ntof);
Chris Fallin91473dc2014-12-12 15:58:26 -08001357err2:
Chris Fallinfcd88892015-01-13 18:14:39 -08001358 upb_inttable_uninit(&m->itof);
1359err3:
Chris Fallin91473dc2014-12-12 15:58:26 -08001360 free(m);
1361 return NULL;
1362}
1363
1364upb_msgdef *upb_msgdef_dup(const upb_msgdef *m, const void *owner) {
Josh Habermane8ed0212015-06-08 17:56:03 -07001365 bool ok;
1366 upb_msg_field_iter i;
1367 upb_msg_oneof_iter o;
1368
Chris Fallin91473dc2014-12-12 15:58:26 -08001369 upb_msgdef *newm = upb_msgdef_new(owner);
1370 if (!newm) return NULL;
Josh Habermane8ed0212015-06-08 17:56:03 -07001371 ok = upb_def_setfullname(upb_msgdef_upcast_mutable(newm),
1372 upb_def_fullname(upb_msgdef_upcast(m)),
1373 NULL);
Chris Fallinfd1a3ff2015-01-06 15:44:09 -08001374 newm->map_entry = m->map_entry;
Josh Haberman94e54b32016-04-14 12:06:09 -07001375 newm->syntax = m->syntax;
Chris Fallin91473dc2014-12-12 15:58:26 -08001376 UPB_ASSERT_VAR(ok, ok);
Chris Fallinfcd88892015-01-13 18:14:39 -08001377 for(upb_msg_field_begin(&i, m);
1378 !upb_msg_field_done(&i);
1379 upb_msg_field_next(&i)) {
Chris Fallin91473dc2014-12-12 15:58:26 -08001380 upb_fielddef *f = upb_fielddef_dup(upb_msg_iter_field(&i), &f);
Josh Habermane8ed0212015-06-08 17:56:03 -07001381 /* Fields in oneofs are dup'd below. */
Chris Fallinfcd88892015-01-13 18:14:39 -08001382 if (upb_fielddef_containingoneof(f)) continue;
Chris Fallin91473dc2014-12-12 15:58:26 -08001383 if (!f || !upb_msgdef_addfield(newm, f, &f, NULL)) {
1384 upb_msgdef_unref(newm, owner);
1385 return NULL;
1386 }
1387 }
Chris Fallinfcd88892015-01-13 18:14:39 -08001388 for(upb_msg_oneof_begin(&o, m);
1389 !upb_msg_oneof_done(&o);
1390 upb_msg_oneof_next(&o)) {
1391 upb_oneofdef *f = upb_oneofdef_dup(upb_msg_iter_oneof(&o), &f);
1392 if (!f || !upb_msgdef_addoneof(newm, f, &f, NULL)) {
1393 upb_msgdef_unref(newm, owner);
1394 return NULL;
1395 }
1396 }
Chris Fallin91473dc2014-12-12 15:58:26 -08001397 return newm;
1398}
1399
Chris Fallin91473dc2014-12-12 15:58:26 -08001400bool upb_msgdef_freeze(upb_msgdef *m, upb_status *status) {
Josh Habermane8ed0212015-06-08 17:56:03 -07001401 upb_def *d = upb_msgdef_upcast_mutable(m);
Chris Fallin91473dc2014-12-12 15:58:26 -08001402 return upb_def_freeze(&d, 1, status);
1403}
1404
1405const char *upb_msgdef_fullname(const upb_msgdef *m) {
Josh Habermane8ed0212015-06-08 17:56:03 -07001406 return upb_def_fullname(upb_msgdef_upcast(m));
Chris Fallin91473dc2014-12-12 15:58:26 -08001407}
1408
Josh Haberman94e54b32016-04-14 12:06:09 -07001409const char *upb_msgdef_name(const upb_msgdef *m) {
1410 return upb_def_name(upb_msgdef_upcast(m));
1411}
1412
Chris Fallin91473dc2014-12-12 15:58:26 -08001413bool upb_msgdef_setfullname(upb_msgdef *m, const char *fullname,
1414 upb_status *s) {
Josh Habermane8ed0212015-06-08 17:56:03 -07001415 return upb_def_setfullname(upb_msgdef_upcast_mutable(m), fullname, s);
Chris Fallin91473dc2014-12-12 15:58:26 -08001416}
1417
Josh Habermane8ed0212015-06-08 17:56:03 -07001418/* Helper: check that the field |f| is safe to add to msgdef |m|. Set an error
1419 * on status |s| and return false if not. */
Chris Fallinfcd88892015-01-13 18:14:39 -08001420static bool check_field_add(const upb_msgdef *m, const upb_fielddef *f,
1421 upb_status *s) {
1422 if (upb_fielddef_containingtype(f) != NULL) {
1423 upb_status_seterrmsg(s, "fielddef already belongs to a message");
1424 return false;
1425 } else if (upb_fielddef_name(f) == NULL || upb_fielddef_number(f) == 0) {
1426 upb_status_seterrmsg(s, "field name or number were not set");
1427 return false;
1428 } else if (upb_msgdef_ntofz(m, upb_fielddef_name(f)) ||
1429 upb_msgdef_itof(m, upb_fielddef_number(f))) {
1430 upb_status_seterrmsg(s, "duplicate field name or number for field");
1431 return false;
1432 }
1433 return true;
1434}
1435
1436static void add_field(upb_msgdef *m, upb_fielddef *f, const void *ref_donor) {
1437 release_containingtype(f);
1438 f->msg.def = m;
1439 f->msg_is_symbolic = false;
1440 upb_inttable_insert(&m->itof, upb_fielddef_number(f), upb_value_ptr(f));
1441 upb_strtable_insert(&m->ntof, upb_fielddef_name(f), upb_value_ptr(f));
1442 upb_ref2(f, m);
1443 upb_ref2(m, f);
1444 if (ref_donor) upb_fielddef_unref(f, ref_donor);
1445}
1446
Chris Fallin91473dc2014-12-12 15:58:26 -08001447bool upb_msgdef_addfield(upb_msgdef *m, upb_fielddef *f, const void *ref_donor,
1448 upb_status *s) {
Josh Habermane8ed0212015-06-08 17:56:03 -07001449 /* TODO: extensions need to have a separate namespace, because proto2 allows a
1450 * top-level extension (ie. one not in any package) to have the same name as a
1451 * field from the message.
1452 *
1453 * This also implies that there needs to be a separate lookup-by-name method
1454 * for extensions. It seems desirable for iteration to return both extensions
1455 * and non-extensions though.
1456 *
1457 * We also need to validate that the field number is in an extension range iff
1458 * it is an extension.
1459 *
1460 * This method is idempotent. Check if |f| is already part of this msgdef and
1461 * return immediately if so. */
Chris Fallinfcd88892015-01-13 18:14:39 -08001462 if (upb_fielddef_containingtype(f) == m) {
1463 return true;
1464 }
1465
Josh Habermane8ed0212015-06-08 17:56:03 -07001466 /* Check constraints for all fields before performing any action. */
Chris Fallinfcd88892015-01-13 18:14:39 -08001467 if (!check_field_add(m, f, s)) {
Chris Fallin91473dc2014-12-12 15:58:26 -08001468 return false;
Chris Fallinfcd88892015-01-13 18:14:39 -08001469 } else if (upb_fielddef_containingoneof(f) != NULL) {
Josh Habermane8ed0212015-06-08 17:56:03 -07001470 /* Fields in a oneof can only be added by adding the oneof to the msgdef. */
Chris Fallinfcd88892015-01-13 18:14:39 -08001471 upb_status_seterrmsg(s, "fielddef is part of a oneof");
Chris Fallin91473dc2014-12-12 15:58:26 -08001472 return false;
1473 }
1474
Josh Habermane8ed0212015-06-08 17:56:03 -07001475 /* Constraint checks ok, perform the action. */
Chris Fallinfcd88892015-01-13 18:14:39 -08001476 add_field(m, f, ref_donor);
1477 return true;
1478}
1479
1480bool upb_msgdef_addoneof(upb_msgdef *m, upb_oneofdef *o, const void *ref_donor,
1481 upb_status *s) {
Josh Habermane8ed0212015-06-08 17:56:03 -07001482 upb_oneof_iter it;
1483
1484 /* Check various conditions that would prevent this oneof from being added. */
Chris Fallinfcd88892015-01-13 18:14:39 -08001485 if (upb_oneofdef_containingtype(o)) {
1486 upb_status_seterrmsg(s, "oneofdef already belongs to a message");
1487 return false;
1488 } else if (upb_oneofdef_name(o) == NULL) {
1489 upb_status_seterrmsg(s, "oneofdef name was not set");
1490 return false;
1491 } else if (upb_msgdef_ntooz(m, upb_oneofdef_name(o))) {
1492 upb_status_seterrmsg(s, "duplicate oneof name");
1493 return false;
1494 }
1495
Josh Habermane8ed0212015-06-08 17:56:03 -07001496 /* Check that all of the oneof's fields do not conflict with names or numbers
1497 * of fields already in the message. */
Chris Fallinfcd88892015-01-13 18:14:39 -08001498 for (upb_oneof_begin(&it, o); !upb_oneof_done(&it); upb_oneof_next(&it)) {
1499 const upb_fielddef *f = upb_oneof_iter_field(&it);
1500 if (!check_field_add(m, f, s)) {
1501 return false;
1502 }
1503 }
1504
Josh Habermane8ed0212015-06-08 17:56:03 -07001505 /* Everything checks out -- commit now. */
Chris Fallinfcd88892015-01-13 18:14:39 -08001506
Josh Habermane8ed0212015-06-08 17:56:03 -07001507 /* Add oneof itself first. */
Chris Fallinfcd88892015-01-13 18:14:39 -08001508 o->parent = m;
1509 upb_strtable_insert(&m->ntoo, upb_oneofdef_name(o), upb_value_ptr(o));
1510 upb_ref2(o, m);
1511 upb_ref2(m, o);
1512
Josh Habermane8ed0212015-06-08 17:56:03 -07001513 /* Add each field of the oneof directly to the msgdef. */
Chris Fallinfcd88892015-01-13 18:14:39 -08001514 for (upb_oneof_begin(&it, o); !upb_oneof_done(&it); upb_oneof_next(&it)) {
1515 upb_fielddef *f = upb_oneof_iter_field(&it);
1516 add_field(m, f, NULL);
1517 }
1518
1519 if (ref_donor) upb_oneofdef_unref(o, ref_donor);
Chris Fallin91473dc2014-12-12 15:58:26 -08001520
1521 return true;
1522}
1523
1524const upb_fielddef *upb_msgdef_itof(const upb_msgdef *m, uint32_t i) {
1525 upb_value val;
1526 return upb_inttable_lookup32(&m->itof, i, &val) ?
1527 upb_value_getptr(val) : NULL;
1528}
1529
1530const upb_fielddef *upb_msgdef_ntof(const upb_msgdef *m, const char *name,
1531 size_t len) {
1532 upb_value val;
1533 return upb_strtable_lookup2(&m->ntof, name, len, &val) ?
1534 upb_value_getptr(val) : NULL;
1535}
1536
Chris Fallinfcd88892015-01-13 18:14:39 -08001537const upb_oneofdef *upb_msgdef_ntoo(const upb_msgdef *m, const char *name,
1538 size_t len) {
1539 upb_value val;
1540 return upb_strtable_lookup2(&m->ntoo, name, len, &val) ?
1541 upb_value_getptr(val) : NULL;
1542}
1543
Chris Fallin91473dc2014-12-12 15:58:26 -08001544int upb_msgdef_numfields(const upb_msgdef *m) {
1545 return upb_strtable_count(&m->ntof);
1546}
1547
Chris Fallinfcd88892015-01-13 18:14:39 -08001548int upb_msgdef_numoneofs(const upb_msgdef *m) {
1549 return upb_strtable_count(&m->ntoo);
1550}
1551
Chris Fallinfd1a3ff2015-01-06 15:44:09 -08001552void upb_msgdef_setmapentry(upb_msgdef *m, bool map_entry) {
1553 assert(!upb_msgdef_isfrozen(m));
1554 m->map_entry = map_entry;
1555}
1556
1557bool upb_msgdef_mapentry(const upb_msgdef *m) {
1558 return m->map_entry;
1559}
1560
Chris Fallinfcd88892015-01-13 18:14:39 -08001561void upb_msg_field_begin(upb_msg_field_iter *iter, const upb_msgdef *m) {
Chris Fallin91473dc2014-12-12 15:58:26 -08001562 upb_inttable_begin(iter, &m->itof);
1563}
1564
Chris Fallinfcd88892015-01-13 18:14:39 -08001565void upb_msg_field_next(upb_msg_field_iter *iter) { upb_inttable_next(iter); }
Chris Fallin91473dc2014-12-12 15:58:26 -08001566
Chris Fallinfcd88892015-01-13 18:14:39 -08001567bool upb_msg_field_done(const upb_msg_field_iter *iter) {
1568 return upb_inttable_done(iter);
1569}
Chris Fallin91473dc2014-12-12 15:58:26 -08001570
Chris Fallinfcd88892015-01-13 18:14:39 -08001571upb_fielddef *upb_msg_iter_field(const upb_msg_field_iter *iter) {
Chris Fallin91473dc2014-12-12 15:58:26 -08001572 return (upb_fielddef*)upb_value_getptr(upb_inttable_iter_value(iter));
1573}
1574
Chris Fallinfcd88892015-01-13 18:14:39 -08001575void upb_msg_field_iter_setdone(upb_msg_field_iter *iter) {
1576 upb_inttable_iter_setdone(iter);
1577}
1578
1579void upb_msg_oneof_begin(upb_msg_oneof_iter *iter, const upb_msgdef *m) {
1580 upb_strtable_begin(iter, &m->ntoo);
1581}
1582
1583void upb_msg_oneof_next(upb_msg_oneof_iter *iter) { upb_strtable_next(iter); }
1584
1585bool upb_msg_oneof_done(const upb_msg_oneof_iter *iter) {
1586 return upb_strtable_done(iter);
1587}
1588
1589upb_oneofdef *upb_msg_iter_oneof(const upb_msg_oneof_iter *iter) {
1590 return (upb_oneofdef*)upb_value_getptr(upb_strtable_iter_value(iter));
1591}
1592
1593void upb_msg_oneof_iter_setdone(upb_msg_oneof_iter *iter) {
1594 upb_strtable_iter_setdone(iter);
1595}
1596
1597/* upb_oneofdef ***************************************************************/
1598
1599static void visitoneof(const upb_refcounted *r, upb_refcounted_visit *visit,
1600 void *closure) {
1601 const upb_oneofdef *o = (const upb_oneofdef*)r;
1602 upb_oneof_iter i;
1603 for (upb_oneof_begin(&i, o); !upb_oneof_done(&i); upb_oneof_next(&i)) {
1604 const upb_fielddef *f = upb_oneof_iter_field(&i);
Josh Habermane8ed0212015-06-08 17:56:03 -07001605 visit(r, upb_fielddef_upcast2(f), closure);
Chris Fallinfcd88892015-01-13 18:14:39 -08001606 }
1607 if (o->parent) {
Josh Habermane8ed0212015-06-08 17:56:03 -07001608 visit(r, upb_msgdef_upcast2(o->parent), closure);
Chris Fallinfcd88892015-01-13 18:14:39 -08001609 }
1610}
1611
1612static void freeoneof(upb_refcounted *r) {
1613 upb_oneofdef *o = (upb_oneofdef*)r;
1614 upb_strtable_uninit(&o->ntof);
1615 upb_inttable_uninit(&o->itof);
Josh Haberman94e54b32016-04-14 12:06:09 -07001616 free((void*)o->name);
Chris Fallinfcd88892015-01-13 18:14:39 -08001617 free(o);
1618}
1619
1620upb_oneofdef *upb_oneofdef_new(const void *owner) {
1621 static const struct upb_refcounted_vtbl vtbl = {visitoneof, freeoneof};
1622 upb_oneofdef *o = malloc(sizeof(*o));
1623 o->parent = NULL;
1624 if (!o) return NULL;
Josh Haberman94e54b32016-04-14 12:06:09 -07001625 if (!upb_refcounted_init(upb_oneofdef_upcast_mutable(o), &vtbl, owner))
Josh Habermane8ed0212015-06-08 17:56:03 -07001626 goto err2;
Josh Haberman94e54b32016-04-14 12:06:09 -07001627 o->name = NULL;
Chris Fallinfcd88892015-01-13 18:14:39 -08001628 if (!upb_inttable_init(&o->itof, UPB_CTYPE_PTR)) goto err2;
1629 if (!upb_strtable_init(&o->ntof, UPB_CTYPE_PTR)) goto err1;
1630 return o;
1631
1632err1:
1633 upb_inttable_uninit(&o->itof);
1634err2:
1635 free(o);
1636 return NULL;
1637}
1638
1639upb_oneofdef *upb_oneofdef_dup(const upb_oneofdef *o, const void *owner) {
Josh Habermane8ed0212015-06-08 17:56:03 -07001640 bool ok;
1641 upb_oneof_iter i;
Chris Fallinfcd88892015-01-13 18:14:39 -08001642 upb_oneofdef *newo = upb_oneofdef_new(owner);
1643 if (!newo) return NULL;
Josh Haberman94e54b32016-04-14 12:06:09 -07001644 ok = upb_oneofdef_setname(newo, upb_oneofdef_name(o), NULL);
Chris Fallinfcd88892015-01-13 18:14:39 -08001645 UPB_ASSERT_VAR(ok, ok);
Chris Fallinfcd88892015-01-13 18:14:39 -08001646 for (upb_oneof_begin(&i, o); !upb_oneof_done(&i); upb_oneof_next(&i)) {
1647 upb_fielddef *f = upb_fielddef_dup(upb_oneof_iter_field(&i), &f);
1648 if (!f || !upb_oneofdef_addfield(newo, f, &f, NULL)) {
1649 upb_oneofdef_unref(newo, owner);
1650 return NULL;
1651 }
1652 }
1653 return newo;
1654}
1655
Josh Haberman94e54b32016-04-14 12:06:09 -07001656const char *upb_oneofdef_name(const upb_oneofdef *o) { return o->name; }
Chris Fallinfcd88892015-01-13 18:14:39 -08001657
Josh Haberman94e54b32016-04-14 12:06:09 -07001658bool upb_oneofdef_setname(upb_oneofdef *o, const char *name, upb_status *s) {
1659 assert(!upb_oneofdef_isfrozen(o));
Chris Fallinfcd88892015-01-13 18:14:39 -08001660 if (upb_oneofdef_containingtype(o)) {
1661 upb_status_seterrmsg(s, "oneof already added to a message");
1662 return false;
1663 }
Josh Haberman94e54b32016-04-14 12:06:09 -07001664 if (!upb_isident(name, strlen(name), true, s)) return false;
1665 free((void*)o->name);
1666 o->name = upb_strdup(name);
1667 return true;
Chris Fallinfcd88892015-01-13 18:14:39 -08001668}
1669
1670const upb_msgdef *upb_oneofdef_containingtype(const upb_oneofdef *o) {
1671 return o->parent;
1672}
1673
1674int upb_oneofdef_numfields(const upb_oneofdef *o) {
1675 return upb_strtable_count(&o->ntof);
1676}
1677
1678bool upb_oneofdef_addfield(upb_oneofdef *o, upb_fielddef *f,
1679 const void *ref_donor,
1680 upb_status *s) {
1681 assert(!upb_oneofdef_isfrozen(o));
1682 assert(!o->parent || !upb_msgdef_isfrozen(o->parent));
1683
Josh Habermane8ed0212015-06-08 17:56:03 -07001684 /* This method is idempotent. Check if |f| is already part of this oneofdef
1685 * and return immediately if so. */
Chris Fallinfcd88892015-01-13 18:14:39 -08001686 if (upb_fielddef_containingoneof(f) == o) {
1687 return true;
1688 }
1689
Josh Habermane8ed0212015-06-08 17:56:03 -07001690 /* The field must have an OPTIONAL label. */
Chris Fallinfcd88892015-01-13 18:14:39 -08001691 if (upb_fielddef_label(f) != UPB_LABEL_OPTIONAL) {
1692 upb_status_seterrmsg(s, "fields in oneof must have OPTIONAL label");
1693 return false;
1694 }
1695
Josh Habermane8ed0212015-06-08 17:56:03 -07001696 /* Check that no field with this name or number exists already in the oneof.
1697 * Also check that the field is not already part of a oneof. */
Chris Fallinfcd88892015-01-13 18:14:39 -08001698 if (upb_fielddef_name(f) == NULL || upb_fielddef_number(f) == 0) {
1699 upb_status_seterrmsg(s, "field name or number were not set");
1700 return false;
1701 } else if (upb_oneofdef_itof(o, upb_fielddef_number(f)) ||
1702 upb_oneofdef_ntofz(o, upb_fielddef_name(f))) {
1703 upb_status_seterrmsg(s, "duplicate field name or number");
1704 return false;
1705 } else if (upb_fielddef_containingoneof(f) != NULL) {
1706 upb_status_seterrmsg(s, "fielddef already belongs to a oneof");
1707 return false;
1708 }
1709
Josh Habermane8ed0212015-06-08 17:56:03 -07001710 /* We allow adding a field to the oneof either if the field is not part of a
1711 * msgdef, or if it is and we are also part of the same msgdef. */
Chris Fallinfcd88892015-01-13 18:14:39 -08001712 if (o->parent == NULL) {
Josh Habermane8ed0212015-06-08 17:56:03 -07001713 /* If we're not in a msgdef, the field cannot be either. Otherwise we would
1714 * need to magically add this oneof to a msgdef to remain consistent, which
1715 * is surprising behavior. */
Chris Fallinfcd88892015-01-13 18:14:39 -08001716 if (upb_fielddef_containingtype(f) != NULL) {
1717 upb_status_seterrmsg(s, "fielddef already belongs to a message, but "
1718 "oneof does not");
1719 return false;
1720 }
1721 } else {
Josh Habermane8ed0212015-06-08 17:56:03 -07001722 /* If we're in a msgdef, the user can add fields that either aren't in any
1723 * msgdef (in which case they're added to our msgdef) or already a part of
1724 * our msgdef. */
Chris Fallinfcd88892015-01-13 18:14:39 -08001725 if (upb_fielddef_containingtype(f) != NULL &&
1726 upb_fielddef_containingtype(f) != o->parent) {
1727 upb_status_seterrmsg(s, "fielddef belongs to a different message "
1728 "than oneof");
1729 return false;
1730 }
1731 }
1732
Josh Habermane8ed0212015-06-08 17:56:03 -07001733 /* Commit phase. First add the field to our parent msgdef, if any, because
1734 * that may fail; then add the field to our own tables. */
Chris Fallinfcd88892015-01-13 18:14:39 -08001735
1736 if (o->parent != NULL && upb_fielddef_containingtype(f) == NULL) {
1737 if (!upb_msgdef_addfield((upb_msgdef*)o->parent, f, NULL, s)) {
1738 return false;
1739 }
1740 }
1741
1742 release_containingtype(f);
1743 f->oneof = o;
1744 upb_inttable_insert(&o->itof, upb_fielddef_number(f), upb_value_ptr(f));
1745 upb_strtable_insert(&o->ntof, upb_fielddef_name(f), upb_value_ptr(f));
1746 upb_ref2(f, o);
1747 upb_ref2(o, f);
1748 if (ref_donor) upb_fielddef_unref(f, ref_donor);
1749
1750 return true;
1751}
1752
1753const upb_fielddef *upb_oneofdef_ntof(const upb_oneofdef *o,
1754 const char *name, size_t length) {
1755 upb_value val;
1756 return upb_strtable_lookup2(&o->ntof, name, length, &val) ?
1757 upb_value_getptr(val) : NULL;
1758}
1759
1760const upb_fielddef *upb_oneofdef_itof(const upb_oneofdef *o, uint32_t num) {
1761 upb_value val;
1762 return upb_inttable_lookup32(&o->itof, num, &val) ?
1763 upb_value_getptr(val) : NULL;
1764}
1765
1766void upb_oneof_begin(upb_oneof_iter *iter, const upb_oneofdef *o) {
1767 upb_inttable_begin(iter, &o->itof);
1768}
1769
1770void upb_oneof_next(upb_oneof_iter *iter) {
1771 upb_inttable_next(iter);
1772}
1773
1774bool upb_oneof_done(upb_oneof_iter *iter) {
1775 return upb_inttable_done(iter);
1776}
1777
1778upb_fielddef *upb_oneof_iter_field(const upb_oneof_iter *iter) {
1779 return (upb_fielddef*)upb_value_getptr(upb_inttable_iter_value(iter));
1780}
1781
1782void upb_oneof_iter_setdone(upb_oneof_iter *iter) {
Chris Fallin91473dc2014-12-12 15:58:26 -08001783 upb_inttable_iter_setdone(iter);
1784}
Chris Fallind3262772015-05-14 18:24:26 -07001785
Josh Haberman94e54b32016-04-14 12:06:09 -07001786/* upb_filedef ****************************************************************/
1787
1788static void visitfiledef(const upb_refcounted *r, upb_refcounted_visit *visit,
1789 void *closure) {
1790 const upb_filedef *f = (const upb_filedef*)r;
1791 size_t i;
1792
1793 for(i = 0; i < upb_filedef_defcount(f); i++) {
1794 visit(r, upb_def_upcast(upb_filedef_def(f, i)), closure);
1795 }
1796}
1797
1798static void freefiledef(upb_refcounted *r) {
1799 upb_filedef *f = (upb_filedef*)r;
1800 size_t i;
1801
1802 for(i = 0; i < upb_filedef_depcount(f); i++) {
1803 upb_filedef_unref(upb_filedef_dep(f, i), f);
1804 }
1805
1806 upb_inttable_uninit(&f->defs);
1807 upb_inttable_uninit(&f->deps);
1808 free((void*)f->name);
1809 free((void*)f->package);
1810 free(f);
1811}
1812
1813upb_filedef *upb_filedef_new(const void *owner) {
1814 static const struct upb_refcounted_vtbl vtbl = {visitfiledef, freefiledef};
1815 upb_filedef *f = malloc(sizeof(*f));
1816
1817 if (!f) {
1818 return NULL;
1819 }
1820
1821 f->package = NULL;
1822 f->name = NULL;
1823 f->syntax = UPB_SYNTAX_PROTO2;
1824
1825 if (!upb_refcounted_init(upb_filedef_upcast_mutable(f), &vtbl, owner)) {
1826 goto err;
1827 }
1828
1829 if (!upb_inttable_init(&f->defs, UPB_CTYPE_CONSTPTR)) {
1830 goto err;
1831 }
1832
1833 if (!upb_inttable_init(&f->deps, UPB_CTYPE_CONSTPTR)) {
1834 goto err2;
1835 }
1836
1837 return f;
1838
1839
1840err2:
1841 upb_inttable_uninit(&f->defs);
1842
1843err:
1844 free(f);
1845 return NULL;
1846}
1847
1848const char *upb_filedef_name(const upb_filedef *f) {
1849 return f->name;
1850}
1851
1852const char *upb_filedef_package(const upb_filedef *f) {
1853 return f->package;
1854}
1855
1856upb_syntax_t upb_filedef_syntax(const upb_filedef *f) {
1857 return f->syntax;
1858}
1859
1860size_t upb_filedef_defcount(const upb_filedef *f) {
1861 return upb_inttable_count(&f->defs);
1862}
1863
1864size_t upb_filedef_depcount(const upb_filedef *f) {
1865 return upb_inttable_count(&f->deps);
1866}
1867
1868const upb_def *upb_filedef_def(const upb_filedef *f, size_t i) {
1869 upb_value v;
1870
1871 if (upb_inttable_lookup32(&f->defs, i, &v)) {
1872 return upb_value_getconstptr(v);
1873 } else {
1874 return NULL;
1875 }
1876}
1877
1878const upb_filedef *upb_filedef_dep(const upb_filedef *f, size_t i) {
1879 upb_value v;
1880
1881 if (upb_inttable_lookup32(&f->deps, i, &v)) {
1882 return upb_value_getconstptr(v);
1883 } else {
1884 return NULL;
1885 }
1886}
1887
1888bool upb_filedef_setname(upb_filedef *f, const char *name, upb_status *s) {
1889 name = upb_strdup(name);
1890 if (!name) {
1891 upb_status_seterrmsg(s, "Out of memory");
1892 return false;
1893 }
1894 free((void*)f->name);
1895 f->name = name;
1896 return true;
1897}
1898
1899bool upb_filedef_setpackage(upb_filedef *f, const char *package,
1900 upb_status *s) {
1901 if (!upb_isident(package, strlen(package), true, s)) return false;
1902 package = upb_strdup(package);
1903 if (!package) {
1904 upb_status_seterrmsg(s, "Out of memory");
1905 return false;
1906 }
1907 free((void*)f->package);
1908 f->package = package;
1909 return true;
1910}
1911
1912bool upb_filedef_setsyntax(upb_filedef *f, upb_syntax_t syntax,
1913 upb_status *s) {
1914 UPB_UNUSED(s);
1915 if (syntax != UPB_SYNTAX_PROTO2 &&
1916 syntax != UPB_SYNTAX_PROTO3) {
1917 upb_status_seterrmsg(s, "Unknown syntax value.");
1918 return false;
1919 }
1920 f->syntax = syntax;
1921
1922 {
1923 /* Set all messages in this file to match. */
1924 size_t i;
1925 for (i = 0; i < upb_filedef_defcount(f); i++) {
1926 /* Casting const away is safe since all defs in mutable filedef must
1927 * also be mutable. */
1928 upb_def *def = (upb_def*)upb_filedef_def(f, i);
1929
1930 upb_msgdef *m = upb_dyncast_msgdef_mutable(def);
1931 if (m) {
1932 m->syntax = syntax;
1933 }
1934 }
1935 }
1936
1937 return true;
1938}
1939
1940bool upb_filedef_adddef(upb_filedef *f, upb_def *def, const void *ref_donor,
1941 upb_status *s) {
1942 if (def->file) {
1943 upb_status_seterrmsg(s, "Def is already part of another filedef.");
1944 return false;
1945 }
1946
1947 if (upb_inttable_push(&f->defs, upb_value_constptr(def))) {
1948 def->file = f;
1949 upb_ref2(def, f);
1950 if (ref_donor) upb_def_unref(def, ref_donor);
1951 if (def->type == UPB_DEF_MSG) {
1952 upb_downcast_msgdef_mutable(def)->syntax = f->syntax;
1953 }
1954 return true;
1955 } else {
1956 upb_status_seterrmsg(s, "Out of memory.");
1957 return false;
1958 }
1959}
1960
1961bool upb_filedef_adddep(upb_filedef *f, const upb_filedef *dep) {
1962 if (upb_inttable_push(&f->deps, upb_value_constptr(dep))) {
1963 /* Regular ref instead of ref2 because files can't form cycles. */
1964 upb_filedef_ref(dep, f);
1965 return true;
1966 } else {
1967 return false;
1968 }
1969}
1970
Chris Fallind3262772015-05-14 18:24:26 -07001971
1972#include <stdlib.h>
1973#include <stdio.h>
1974#include <string.h>
1975
1976typedef struct cleanup_ent {
1977 upb_cleanup_func *cleanup;
1978 void *ud;
1979 struct cleanup_ent *next;
1980} cleanup_ent;
1981
1982static void *seeded_alloc(void *ud, void *ptr, size_t oldsize, size_t size);
1983
1984/* Default allocator **********************************************************/
1985
Josh Habermane8ed0212015-06-08 17:56:03 -07001986/* Just use realloc, keeping all allocated blocks in a linked list to destroy at
1987 * the end. */
Chris Fallind3262772015-05-14 18:24:26 -07001988
1989typedef struct mem_block {
Josh Habermane8ed0212015-06-08 17:56:03 -07001990 /* List is doubly-linked, because in cases where realloc() moves an existing
1991 * block, we need to be able to remove the old pointer from the list
1992 * efficiently. */
Chris Fallind3262772015-05-14 18:24:26 -07001993 struct mem_block *prev, *next;
1994#ifndef NDEBUG
Josh Habermane8ed0212015-06-08 17:56:03 -07001995 size_t size; /* Doesn't include mem_block structure. */
Chris Fallind3262772015-05-14 18:24:26 -07001996#endif
Chris Fallind3262772015-05-14 18:24:26 -07001997} mem_block;
1998
1999typedef struct {
2000 mem_block *head;
2001} default_alloc_ud;
2002
2003static void *default_alloc(void *_ud, void *ptr, size_t oldsize, size_t size) {
Chris Fallind3262772015-05-14 18:24:26 -07002004 default_alloc_ud *ud = _ud;
Josh Habermane8ed0212015-06-08 17:56:03 -07002005 mem_block *from, *block;
2006 void *ret;
2007 UPB_UNUSED(oldsize);
Chris Fallind3262772015-05-14 18:24:26 -07002008
Josh Habermane8ed0212015-06-08 17:56:03 -07002009 from = ptr ? (void*)((char*)ptr - sizeof(mem_block)) : NULL;
Chris Fallind3262772015-05-14 18:24:26 -07002010
2011#ifndef NDEBUG
2012 if (from) {
2013 assert(oldsize <= from->size);
2014 }
2015#endif
2016
Josh Habermane8ed0212015-06-08 17:56:03 -07002017 /* TODO(haberman): we probably need to provide even better alignment here,
2018 * like 16-byte alignment of the returned data pointer. */
2019 block = realloc(from, size + sizeof(mem_block));
Chris Fallind3262772015-05-14 18:24:26 -07002020 if (!block) return NULL;
Josh Habermane8ed0212015-06-08 17:56:03 -07002021 ret = (char*)block + sizeof(*block);
Chris Fallind3262772015-05-14 18:24:26 -07002022
2023#ifndef NDEBUG
2024 block->size = size;
2025#endif
2026
2027 if (from) {
2028 if (block != from) {
Josh Habermane8ed0212015-06-08 17:56:03 -07002029 /* The block was moved, so pointers in next and prev blocks must be
2030 * updated to its new location. */
Chris Fallind3262772015-05-14 18:24:26 -07002031 if (block->next) block->next->prev = block;
2032 if (block->prev) block->prev->next = block;
Josh Habermanfb8ed702015-06-22 17:23:55 -07002033 if (ud->head == from) ud->head = block;
Chris Fallind3262772015-05-14 18:24:26 -07002034 }
2035 } else {
Josh Habermane8ed0212015-06-08 17:56:03 -07002036 /* Insert at head of linked list. */
Chris Fallind3262772015-05-14 18:24:26 -07002037 block->prev = NULL;
2038 block->next = ud->head;
2039 if (block->next) block->next->prev = block;
2040 ud->head = block;
2041 }
2042
Josh Habermane8ed0212015-06-08 17:56:03 -07002043 return ret;
Chris Fallind3262772015-05-14 18:24:26 -07002044}
2045
2046static void default_alloc_cleanup(void *_ud) {
2047 default_alloc_ud *ud = _ud;
2048 mem_block *block = ud->head;
2049
2050 while (block) {
2051 void *to_free = block;
2052 block = block->next;
2053 free(to_free);
2054 }
2055}
2056
2057
2058/* Standard error functions ***************************************************/
2059
2060static bool default_err(void *ud, const upb_status *status) {
2061 UPB_UNUSED(ud);
Josh Habermanfb8ed702015-06-22 17:23:55 -07002062 UPB_UNUSED(status);
Chris Fallind3262772015-05-14 18:24:26 -07002063 return false;
2064}
2065
2066static bool write_err_to(void *ud, const upb_status *status) {
2067 upb_status *copy_to = ud;
2068 upb_status_copy(copy_to, status);
2069 return false;
2070}
2071
2072
2073/* upb_env ********************************************************************/
2074
2075void upb_env_init(upb_env *e) {
Josh Habermane8ed0212015-06-08 17:56:03 -07002076 default_alloc_ud *ud = (default_alloc_ud*)&e->default_alloc_ud;
Chris Fallind3262772015-05-14 18:24:26 -07002077 e->ok_ = true;
2078 e->bytes_allocated = 0;
2079 e->cleanup_head = NULL;
2080
Chris Fallind3262772015-05-14 18:24:26 -07002081 ud->head = NULL;
2082
Josh Habermane8ed0212015-06-08 17:56:03 -07002083 /* Set default functions. */
Chris Fallind3262772015-05-14 18:24:26 -07002084 upb_env_setallocfunc(e, default_alloc, ud);
2085 upb_env_seterrorfunc(e, default_err, NULL);
2086}
2087
2088void upb_env_uninit(upb_env *e) {
2089 cleanup_ent *ent = e->cleanup_head;
2090
2091 while (ent) {
2092 ent->cleanup(ent->ud);
2093 ent = ent->next;
2094 }
2095
Josh Habermane8ed0212015-06-08 17:56:03 -07002096 /* Must do this after running cleanup functions, because this will delete
2097 the memory we store our cleanup entries in! */
Chris Fallind3262772015-05-14 18:24:26 -07002098 if (e->alloc == default_alloc) {
2099 default_alloc_cleanup(e->alloc_ud);
2100 }
2101}
2102
2103UPB_FORCEINLINE void upb_env_setallocfunc(upb_env *e, upb_alloc_func *alloc,
2104 void *ud) {
2105 e->alloc = alloc;
2106 e->alloc_ud = ud;
2107}
2108
2109UPB_FORCEINLINE void upb_env_seterrorfunc(upb_env *e, upb_error_func *func,
2110 void *ud) {
2111 e->err = func;
2112 e->err_ud = ud;
2113}
2114
2115void upb_env_reporterrorsto(upb_env *e, upb_status *status) {
2116 e->err = write_err_to;
2117 e->err_ud = status;
2118}
2119
2120bool upb_env_ok(const upb_env *e) {
2121 return e->ok_;
2122}
2123
2124bool upb_env_reporterror(upb_env *e, const upb_status *status) {
2125 e->ok_ = false;
2126 return e->err(e->err_ud, status);
2127}
2128
2129bool upb_env_addcleanup(upb_env *e, upb_cleanup_func *func, void *ud) {
2130 cleanup_ent *ent = upb_env_malloc(e, sizeof(cleanup_ent));
2131 if (!ent) return false;
2132
2133 ent->cleanup = func;
2134 ent->ud = ud;
2135 ent->next = e->cleanup_head;
2136 e->cleanup_head = ent;
2137
2138 return true;
2139}
2140
2141void *upb_env_malloc(upb_env *e, size_t size) {
2142 e->bytes_allocated += size;
2143 if (e->alloc == seeded_alloc) {
Josh Habermane8ed0212015-06-08 17:56:03 -07002144 /* This is equivalent to the next branch, but allows inlining for a
2145 * measurable perf benefit. */
Chris Fallind3262772015-05-14 18:24:26 -07002146 return seeded_alloc(e->alloc_ud, NULL, 0, size);
2147 } else {
2148 return e->alloc(e->alloc_ud, NULL, 0, size);
2149 }
2150}
2151
2152void *upb_env_realloc(upb_env *e, void *ptr, size_t oldsize, size_t size) {
Josh Habermane8ed0212015-06-08 17:56:03 -07002153 char *ret;
Chris Fallind3262772015-05-14 18:24:26 -07002154 assert(oldsize <= size);
Josh Habermane8ed0212015-06-08 17:56:03 -07002155 ret = e->alloc(e->alloc_ud, ptr, oldsize, size);
Chris Fallind3262772015-05-14 18:24:26 -07002156
2157#ifndef NDEBUG
Josh Habermane8ed0212015-06-08 17:56:03 -07002158 /* Overwrite non-preserved memory to ensure callers are passing the oldsize
2159 * that they truly require. */
Chris Fallind3262772015-05-14 18:24:26 -07002160 memset(ret + oldsize, 0xff, size - oldsize);
2161#endif
2162
2163 return ret;
2164}
2165
2166size_t upb_env_bytesallocated(const upb_env *e) {
2167 return e->bytes_allocated;
2168}
2169
2170
2171/* upb_seededalloc ************************************************************/
2172
Josh Habermane8ed0212015-06-08 17:56:03 -07002173/* Be conservative and choose 16 in case anyone is using SSE. */
Chris Fallind3262772015-05-14 18:24:26 -07002174static const size_t maxalign = 16;
2175
2176static size_t align_up(size_t size) {
2177 return ((size + maxalign - 1) / maxalign) * maxalign;
2178}
2179
2180UPB_FORCEINLINE static void *seeded_alloc(void *ud, void *ptr, size_t oldsize,
2181 size_t size) {
Josh Habermane8ed0212015-06-08 17:56:03 -07002182 upb_seededalloc *a = ud;
Chris Fallind3262772015-05-14 18:24:26 -07002183
Chris Fallind3262772015-05-14 18:24:26 -07002184 size = align_up(size);
2185
2186 assert(a->mem_limit >= a->mem_ptr);
2187
2188 if (oldsize == 0 && size <= (size_t)(a->mem_limit - a->mem_ptr)) {
Josh Habermane8ed0212015-06-08 17:56:03 -07002189 /* Fast path: we can satisfy from the initial allocation. */
Chris Fallind3262772015-05-14 18:24:26 -07002190 void *ret = a->mem_ptr;
2191 a->mem_ptr += size;
2192 return ret;
2193 } else {
Chris Fallind3262772015-05-14 18:24:26 -07002194 char *chptr = ptr;
Josh Habermane8ed0212015-06-08 17:56:03 -07002195 /* Slow path: fallback to other allocator. */
2196 a->need_cleanup = true;
2197 /* Is `ptr` part of the user-provided initial block? Don't pass it to the
2198 * default allocator if so; otherwise, it may try to realloc() the block. */
Chris Fallind3262772015-05-14 18:24:26 -07002199 if (chptr >= a->mem_base && chptr < a->mem_limit) {
Josh Habermanfb8ed702015-06-22 17:23:55 -07002200 void *ret;
2201 assert(chptr + oldsize <= a->mem_limit);
2202 ret = a->alloc(a->alloc_ud, NULL, 0, size);
2203 if (ret) memcpy(ret, ptr, oldsize);
2204 return ret;
Chris Fallind3262772015-05-14 18:24:26 -07002205 } else {
2206 return a->alloc(a->alloc_ud, ptr, oldsize, size);
2207 }
2208 }
2209}
2210
2211void upb_seededalloc_init(upb_seededalloc *a, void *mem, size_t len) {
Josh Habermane8ed0212015-06-08 17:56:03 -07002212 default_alloc_ud *ud = (default_alloc_ud*)&a->default_alloc_ud;
Chris Fallind3262772015-05-14 18:24:26 -07002213 a->mem_base = mem;
2214 a->mem_ptr = mem;
2215 a->mem_limit = (char*)mem + len;
2216 a->need_cleanup = false;
2217 a->returned_allocfunc = false;
2218
Chris Fallind3262772015-05-14 18:24:26 -07002219 ud->head = NULL;
2220
2221 upb_seededalloc_setfallbackalloc(a, default_alloc, ud);
2222}
2223
2224void upb_seededalloc_uninit(upb_seededalloc *a) {
2225 if (a->alloc == default_alloc && a->need_cleanup) {
2226 default_alloc_cleanup(a->alloc_ud);
2227 }
2228}
2229
2230UPB_FORCEINLINE void upb_seededalloc_setfallbackalloc(upb_seededalloc *a,
2231 upb_alloc_func *alloc,
2232 void *ud) {
2233 assert(!a->returned_allocfunc);
2234 a->alloc = alloc;
2235 a->alloc_ud = ud;
2236}
2237
2238upb_alloc_func *upb_seededalloc_getallocfunc(upb_seededalloc *a) {
2239 a->returned_allocfunc = true;
2240 return seeded_alloc;
2241}
2242/*
Josh Haberman181c7f22015-07-15 11:05:10 -07002243** TODO(haberman): it's unclear whether a lot of the consistency checks should
2244** assert() or return false.
2245*/
Chris Fallin91473dc2014-12-12 15:58:26 -08002246
2247
2248#include <stdlib.h>
2249#include <string.h>
2250
2251
Josh Habermane8ed0212015-06-08 17:56:03 -07002252
2253/* Defined for the sole purpose of having a unique pointer value for
2254 * UPB_NO_CLOSURE. */
Chris Fallin91473dc2014-12-12 15:58:26 -08002255char _upb_noclosure;
2256
2257static void freehandlers(upb_refcounted *r) {
2258 upb_handlers *h = (upb_handlers*)r;
2259
2260 upb_inttable_iter i;
2261 upb_inttable_begin(&i, &h->cleanup_);
2262 for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
2263 void *val = (void*)upb_inttable_iter_key(&i);
2264 upb_value func_val = upb_inttable_iter_value(&i);
2265 upb_handlerfree *func = upb_value_getfptr(func_val);
2266 func(val);
2267 }
2268
2269 upb_inttable_uninit(&h->cleanup_);
2270 upb_msgdef_unref(h->msg, h);
2271 free(h->sub);
2272 free(h);
2273}
2274
2275static void visithandlers(const upb_refcounted *r, upb_refcounted_visit *visit,
2276 void *closure) {
2277 const upb_handlers *h = (const upb_handlers*)r;
Chris Fallinfcd88892015-01-13 18:14:39 -08002278 upb_msg_field_iter i;
2279 for(upb_msg_field_begin(&i, h->msg);
2280 !upb_msg_field_done(&i);
2281 upb_msg_field_next(&i)) {
Chris Fallin91473dc2014-12-12 15:58:26 -08002282 upb_fielddef *f = upb_msg_iter_field(&i);
Josh Habermane8ed0212015-06-08 17:56:03 -07002283 const upb_handlers *sub;
Chris Fallin91473dc2014-12-12 15:58:26 -08002284 if (!upb_fielddef_issubmsg(f)) continue;
Josh Habermane8ed0212015-06-08 17:56:03 -07002285 sub = upb_handlers_getsubhandlers(h, f);
2286 if (sub) visit(r, upb_handlers_upcast(sub), closure);
Chris Fallin91473dc2014-12-12 15:58:26 -08002287 }
2288}
2289
2290static const struct upb_refcounted_vtbl vtbl = {visithandlers, freehandlers};
2291
2292typedef struct {
Josh Habermane8ed0212015-06-08 17:56:03 -07002293 upb_inttable tab; /* maps upb_msgdef* -> upb_handlers*. */
Chris Fallin91473dc2014-12-12 15:58:26 -08002294 upb_handlers_callback *callback;
2295 const void *closure;
2296} dfs_state;
2297
Josh Habermane8ed0212015-06-08 17:56:03 -07002298/* TODO(haberman): discard upb_handlers* objects that do not actually have any
2299 * handlers set and cannot reach any upb_handlers* object that does. This is
2300 * slightly tricky to do correctly. */
Chris Fallin91473dc2014-12-12 15:58:26 -08002301static upb_handlers *newformsg(const upb_msgdef *m, const void *owner,
2302 dfs_state *s) {
Josh Habermane8ed0212015-06-08 17:56:03 -07002303 upb_msg_field_iter i;
Chris Fallin91473dc2014-12-12 15:58:26 -08002304 upb_handlers *h = upb_handlers_new(m, owner);
2305 if (!h) return NULL;
2306 if (!upb_inttable_insertptr(&s->tab, m, upb_value_ptr(h))) goto oom;
2307
2308 s->callback(s->closure, h);
2309
Josh Habermane8ed0212015-06-08 17:56:03 -07002310 /* For each submessage field, get or create a handlers object and set it as
2311 * the subhandlers. */
Chris Fallinfcd88892015-01-13 18:14:39 -08002312 for(upb_msg_field_begin(&i, m);
2313 !upb_msg_field_done(&i);
2314 upb_msg_field_next(&i)) {
Chris Fallin91473dc2014-12-12 15:58:26 -08002315 upb_fielddef *f = upb_msg_iter_field(&i);
Josh Habermane8ed0212015-06-08 17:56:03 -07002316 const upb_msgdef *subdef;
2317 upb_value subm_ent;
2318
Chris Fallin91473dc2014-12-12 15:58:26 -08002319 if (!upb_fielddef_issubmsg(f)) continue;
2320
Josh Habermane8ed0212015-06-08 17:56:03 -07002321 subdef = upb_downcast_msgdef(upb_fielddef_subdef(f));
Chris Fallin91473dc2014-12-12 15:58:26 -08002322 if (upb_inttable_lookupptr(&s->tab, subdef, &subm_ent)) {
2323 upb_handlers_setsubhandlers(h, f, upb_value_getptr(subm_ent));
2324 } else {
2325 upb_handlers *sub_mh = newformsg(subdef, &sub_mh, s);
2326 if (!sub_mh) goto oom;
2327 upb_handlers_setsubhandlers(h, f, sub_mh);
2328 upb_handlers_unref(sub_mh, &sub_mh);
2329 }
2330 }
2331 return h;
2332
2333oom:
2334 upb_handlers_unref(h, owner);
2335 return NULL;
2336}
2337
Josh Habermane8ed0212015-06-08 17:56:03 -07002338/* Given a selector for a STARTSUBMSG handler, resolves to a pointer to the
2339 * subhandlers for this submessage field. */
Chris Fallin91473dc2014-12-12 15:58:26 -08002340#define SUBH(h, selector) (h->sub[selector])
2341
Josh Habermane8ed0212015-06-08 17:56:03 -07002342/* The selector for a submessage field is the field index. */
Chris Fallin91473dc2014-12-12 15:58:26 -08002343#define SUBH_F(h, f) SUBH(h, f->index_)
2344
2345static int32_t trygetsel(upb_handlers *h, const upb_fielddef *f,
2346 upb_handlertype_t type) {
2347 upb_selector_t sel;
2348 assert(!upb_handlers_isfrozen(h));
2349 if (upb_handlers_msgdef(h) != upb_fielddef_containingtype(f)) {
2350 upb_status_seterrf(
2351 &h->status_, "type mismatch: field %s does not belong to message %s",
2352 upb_fielddef_name(f), upb_msgdef_fullname(upb_handlers_msgdef(h)));
2353 return -1;
2354 }
2355 if (!upb_handlers_getselector(f, type, &sel)) {
2356 upb_status_seterrf(
2357 &h->status_,
2358 "type mismatch: cannot register handler type %d for field %s",
2359 type, upb_fielddef_name(f));
2360 return -1;
2361 }
2362 return sel;
2363}
2364
2365static upb_selector_t handlers_getsel(upb_handlers *h, const upb_fielddef *f,
2366 upb_handlertype_t type) {
2367 int32_t sel = trygetsel(h, f, type);
2368 assert(sel >= 0);
2369 return sel;
2370}
2371
2372static const void **returntype(upb_handlers *h, const upb_fielddef *f,
2373 upb_handlertype_t type) {
2374 return &h->table[handlers_getsel(h, f, type)].attr.return_closure_type_;
2375}
2376
2377static bool doset(upb_handlers *h, int32_t sel, const upb_fielddef *f,
2378 upb_handlertype_t type, upb_func *func,
2379 upb_handlerattr *attr) {
Josh Habermane8ed0212015-06-08 17:56:03 -07002380 upb_handlerattr set_attr = UPB_HANDLERATTR_INITIALIZER;
2381 const void *closure_type;
2382 const void **context_closure_type;
2383
Chris Fallin91473dc2014-12-12 15:58:26 -08002384 assert(!upb_handlers_isfrozen(h));
2385
2386 if (sel < 0) {
2387 upb_status_seterrmsg(&h->status_,
2388 "incorrect handler type for this field.");
2389 return false;
2390 }
2391
2392 if (h->table[sel].func) {
2393 upb_status_seterrmsg(&h->status_,
2394 "cannot change handler once it has been set.");
2395 return false;
2396 }
2397
Chris Fallin91473dc2014-12-12 15:58:26 -08002398 if (attr) {
2399 set_attr = *attr;
2400 }
2401
Josh Habermane8ed0212015-06-08 17:56:03 -07002402 /* Check that the given closure type matches the closure type that has been
2403 * established for this context (if any). */
2404 closure_type = upb_handlerattr_closuretype(&set_attr);
Chris Fallin91473dc2014-12-12 15:58:26 -08002405
2406 if (type == UPB_HANDLER_STRING) {
2407 context_closure_type = returntype(h, f, UPB_HANDLER_STARTSTR);
2408 } else if (f && upb_fielddef_isseq(f) &&
2409 type != UPB_HANDLER_STARTSEQ &&
2410 type != UPB_HANDLER_ENDSEQ) {
2411 context_closure_type = returntype(h, f, UPB_HANDLER_STARTSEQ);
2412 } else {
2413 context_closure_type = &h->top_closure_type;
2414 }
2415
2416 if (closure_type && *context_closure_type &&
2417 closure_type != *context_closure_type) {
Josh Habermane8ed0212015-06-08 17:56:03 -07002418 /* TODO(haberman): better message for debugging. */
Chris Fallind3262772015-05-14 18:24:26 -07002419 if (f) {
2420 upb_status_seterrf(&h->status_,
2421 "closure type does not match for field %s",
2422 upb_fielddef_name(f));
2423 } else {
2424 upb_status_seterrmsg(
2425 &h->status_, "closure type does not match for message-level handler");
2426 }
Chris Fallin91473dc2014-12-12 15:58:26 -08002427 return false;
2428 }
2429
2430 if (closure_type)
2431 *context_closure_type = closure_type;
2432
Josh Habermane8ed0212015-06-08 17:56:03 -07002433 /* If this is a STARTSEQ or STARTSTR handler, check that the returned pointer
2434 * matches any pre-existing expectations about what type is expected. */
Chris Fallin91473dc2014-12-12 15:58:26 -08002435 if (type == UPB_HANDLER_STARTSEQ || type == UPB_HANDLER_STARTSTR) {
2436 const void *return_type = upb_handlerattr_returnclosuretype(&set_attr);
2437 const void *table_return_type =
2438 upb_handlerattr_returnclosuretype(&h->table[sel].attr);
2439 if (return_type && table_return_type && return_type != table_return_type) {
2440 upb_status_seterrmsg(&h->status_, "closure return type does not match");
2441 return false;
2442 }
2443
2444 if (table_return_type && !return_type)
2445 upb_handlerattr_setreturnclosuretype(&set_attr, table_return_type);
2446 }
2447
2448 h->table[sel].func = (upb_func*)func;
2449 h->table[sel].attr = set_attr;
2450 return true;
2451}
2452
Josh Habermane8ed0212015-06-08 17:56:03 -07002453/* Returns the effective closure type for this handler (which will propagate
2454 * from outer frames if this frame has no START* handler). Not implemented for
2455 * UPB_HANDLER_STRING at the moment since this is not needed. Returns NULL is
2456 * the effective closure type is unspecified (either no handler was registered
2457 * to specify it or the handler that was registered did not specify the closure
2458 * type). */
Chris Fallin91473dc2014-12-12 15:58:26 -08002459const void *effective_closure_type(upb_handlers *h, const upb_fielddef *f,
2460 upb_handlertype_t type) {
Josh Habermane8ed0212015-06-08 17:56:03 -07002461 const void *ret;
Chris Fallin91473dc2014-12-12 15:58:26 -08002462 upb_selector_t sel;
Josh Habermane8ed0212015-06-08 17:56:03 -07002463
2464 assert(type != UPB_HANDLER_STRING);
2465 ret = h->top_closure_type;
2466
Chris Fallin91473dc2014-12-12 15:58:26 -08002467 if (upb_fielddef_isseq(f) &&
2468 type != UPB_HANDLER_STARTSEQ &&
2469 type != UPB_HANDLER_ENDSEQ &&
2470 h->table[sel = handlers_getsel(h, f, UPB_HANDLER_STARTSEQ)].func) {
2471 ret = upb_handlerattr_returnclosuretype(&h->table[sel].attr);
2472 }
2473
2474 if (type == UPB_HANDLER_STRING &&
2475 h->table[sel = handlers_getsel(h, f, UPB_HANDLER_STARTSTR)].func) {
2476 ret = upb_handlerattr_returnclosuretype(&h->table[sel].attr);
2477 }
2478
Josh Habermane8ed0212015-06-08 17:56:03 -07002479 /* The effective type of the submessage; not used yet.
2480 * if (type == SUBMESSAGE &&
2481 * h->table[sel = handlers_getsel(h, f, UPB_HANDLER_STARTSUBMSG)].func) {
2482 * ret = upb_handlerattr_returnclosuretype(&h->table[sel].attr);
2483 * } */
Chris Fallin91473dc2014-12-12 15:58:26 -08002484
2485 return ret;
2486}
2487
Josh Habermane8ed0212015-06-08 17:56:03 -07002488/* Checks whether the START* handler specified by f & type is missing even
2489 * though it is required to convert the established type of an outer frame
2490 * ("closure_type") into the established type of an inner frame (represented in
2491 * the return closure type of this handler's attr. */
Chris Fallin91473dc2014-12-12 15:58:26 -08002492bool checkstart(upb_handlers *h, const upb_fielddef *f, upb_handlertype_t type,
2493 upb_status *status) {
Josh Habermane8ed0212015-06-08 17:56:03 -07002494 const void *closure_type;
2495 const upb_handlerattr *attr;
2496 const void *return_closure_type;
2497
Chris Fallin91473dc2014-12-12 15:58:26 -08002498 upb_selector_t sel = handlers_getsel(h, f, type);
2499 if (h->table[sel].func) return true;
Josh Habermane8ed0212015-06-08 17:56:03 -07002500 closure_type = effective_closure_type(h, f, type);
2501 attr = &h->table[sel].attr;
2502 return_closure_type = upb_handlerattr_returnclosuretype(attr);
Chris Fallin91473dc2014-12-12 15:58:26 -08002503 if (closure_type && return_closure_type &&
2504 closure_type != return_closure_type) {
2505 upb_status_seterrf(status,
2506 "expected start handler to return sub type for field %f",
2507 upb_fielddef_name(f));
2508 return false;
2509 }
2510 return true;
2511}
2512
2513/* Public interface ***********************************************************/
2514
Chris Fallin91473dc2014-12-12 15:58:26 -08002515upb_handlers *upb_handlers_new(const upb_msgdef *md, const void *owner) {
Josh Habermane8ed0212015-06-08 17:56:03 -07002516 int extra;
2517 upb_handlers *h;
2518
Chris Fallin91473dc2014-12-12 15:58:26 -08002519 assert(upb_msgdef_isfrozen(md));
2520
Josh Habermane8ed0212015-06-08 17:56:03 -07002521 extra = sizeof(upb_handlers_tabent) * (md->selector_count - 1);
2522 h = calloc(sizeof(*h) + extra, 1);
Chris Fallin91473dc2014-12-12 15:58:26 -08002523 if (!h) return NULL;
2524
2525 h->msg = md;
2526 upb_msgdef_ref(h->msg, h);
2527 upb_status_clear(&h->status_);
2528 h->sub = calloc(md->submsg_field_count, sizeof(*h->sub));
2529 if (!h->sub) goto oom;
Josh Habermane8ed0212015-06-08 17:56:03 -07002530 if (!upb_refcounted_init(upb_handlers_upcast_mutable(h), &vtbl, owner))
2531 goto oom;
Chris Fallin91473dc2014-12-12 15:58:26 -08002532 if (!upb_inttable_init(&h->cleanup_, UPB_CTYPE_FPTR)) goto oom;
2533
Josh Habermane8ed0212015-06-08 17:56:03 -07002534 /* calloc() above initialized all handlers to NULL. */
Chris Fallin91473dc2014-12-12 15:58:26 -08002535 return h;
2536
2537oom:
Josh Habermane8ed0212015-06-08 17:56:03 -07002538 freehandlers(upb_handlers_upcast_mutable(h));
Chris Fallin91473dc2014-12-12 15:58:26 -08002539 return NULL;
2540}
2541
2542const upb_handlers *upb_handlers_newfrozen(const upb_msgdef *m,
2543 const void *owner,
2544 upb_handlers_callback *callback,
2545 const void *closure) {
2546 dfs_state state;
Josh Habermane8ed0212015-06-08 17:56:03 -07002547 upb_handlers *ret;
2548 bool ok;
2549 upb_refcounted *r;
2550
Chris Fallin91473dc2014-12-12 15:58:26 -08002551 state.callback = callback;
2552 state.closure = closure;
2553 if (!upb_inttable_init(&state.tab, UPB_CTYPE_PTR)) return NULL;
2554
Josh Habermane8ed0212015-06-08 17:56:03 -07002555 ret = newformsg(m, owner, &state);
Chris Fallin91473dc2014-12-12 15:58:26 -08002556
2557 upb_inttable_uninit(&state.tab);
2558 if (!ret) return NULL;
2559
Josh Habermane8ed0212015-06-08 17:56:03 -07002560 r = upb_handlers_upcast_mutable(ret);
2561 ok = upb_refcounted_freeze(&r, 1, NULL, UPB_MAX_HANDLER_DEPTH);
Chris Fallin91473dc2014-12-12 15:58:26 -08002562 UPB_ASSERT_VAR(ok, ok);
2563
2564 return ret;
2565}
2566
2567const upb_status *upb_handlers_status(upb_handlers *h) {
2568 assert(!upb_handlers_isfrozen(h));
2569 return &h->status_;
2570}
2571
2572void upb_handlers_clearerr(upb_handlers *h) {
2573 assert(!upb_handlers_isfrozen(h));
2574 upb_status_clear(&h->status_);
2575}
2576
2577#define SETTER(name, handlerctype, handlertype) \
2578 bool upb_handlers_set ## name(upb_handlers *h, const upb_fielddef *f, \
2579 handlerctype func, upb_handlerattr *attr) { \
2580 int32_t sel = trygetsel(h, f, handlertype); \
2581 return doset(h, sel, f, handlertype, (upb_func*)func, attr); \
2582 }
2583
Josh Habermane8ed0212015-06-08 17:56:03 -07002584SETTER(int32, upb_int32_handlerfunc*, UPB_HANDLER_INT32)
2585SETTER(int64, upb_int64_handlerfunc*, UPB_HANDLER_INT64)
2586SETTER(uint32, upb_uint32_handlerfunc*, UPB_HANDLER_UINT32)
2587SETTER(uint64, upb_uint64_handlerfunc*, UPB_HANDLER_UINT64)
2588SETTER(float, upb_float_handlerfunc*, UPB_HANDLER_FLOAT)
2589SETTER(double, upb_double_handlerfunc*, UPB_HANDLER_DOUBLE)
2590SETTER(bool, upb_bool_handlerfunc*, UPB_HANDLER_BOOL)
2591SETTER(startstr, upb_startstr_handlerfunc*, UPB_HANDLER_STARTSTR)
2592SETTER(string, upb_string_handlerfunc*, UPB_HANDLER_STRING)
2593SETTER(endstr, upb_endfield_handlerfunc*, UPB_HANDLER_ENDSTR)
2594SETTER(startseq, upb_startfield_handlerfunc*, UPB_HANDLER_STARTSEQ)
2595SETTER(startsubmsg, upb_startfield_handlerfunc*, UPB_HANDLER_STARTSUBMSG)
2596SETTER(endsubmsg, upb_endfield_handlerfunc*, UPB_HANDLER_ENDSUBMSG)
2597SETTER(endseq, upb_endfield_handlerfunc*, UPB_HANDLER_ENDSEQ)
Chris Fallin91473dc2014-12-12 15:58:26 -08002598
2599#undef SETTER
2600
2601bool upb_handlers_setstartmsg(upb_handlers *h, upb_startmsg_handlerfunc *func,
2602 upb_handlerattr *attr) {
2603 return doset(h, UPB_STARTMSG_SELECTOR, NULL, UPB_HANDLER_INT32,
2604 (upb_func *)func, attr);
2605}
2606
2607bool upb_handlers_setendmsg(upb_handlers *h, upb_endmsg_handlerfunc *func,
2608 upb_handlerattr *attr) {
2609 assert(!upb_handlers_isfrozen(h));
2610 return doset(h, UPB_ENDMSG_SELECTOR, NULL, UPB_HANDLER_INT32,
2611 (upb_func *)func, attr);
2612}
2613
2614bool upb_handlers_setsubhandlers(upb_handlers *h, const upb_fielddef *f,
2615 const upb_handlers *sub) {
2616 assert(sub);
2617 assert(!upb_handlers_isfrozen(h));
2618 assert(upb_fielddef_issubmsg(f));
Josh Habermane8ed0212015-06-08 17:56:03 -07002619 if (SUBH_F(h, f)) return false; /* Can't reset. */
2620 if (upb_msgdef_upcast(upb_handlers_msgdef(sub)) != upb_fielddef_subdef(f)) {
Chris Fallin91473dc2014-12-12 15:58:26 -08002621 return false;
2622 }
2623 SUBH_F(h, f) = sub;
2624 upb_ref2(sub, h);
2625 return true;
2626}
2627
2628const upb_handlers *upb_handlers_getsubhandlers(const upb_handlers *h,
2629 const upb_fielddef *f) {
2630 assert(upb_fielddef_issubmsg(f));
2631 return SUBH_F(h, f);
2632}
2633
2634bool upb_handlers_getattr(const upb_handlers *h, upb_selector_t sel,
2635 upb_handlerattr *attr) {
2636 if (!upb_handlers_gethandler(h, sel))
2637 return false;
2638 *attr = h->table[sel].attr;
2639 return true;
2640}
2641
2642const upb_handlers *upb_handlers_getsubhandlers_sel(const upb_handlers *h,
2643 upb_selector_t sel) {
Josh Habermane8ed0212015-06-08 17:56:03 -07002644 /* STARTSUBMSG selector in sel is the field's selector base. */
Chris Fallin91473dc2014-12-12 15:58:26 -08002645 return SUBH(h, sel - UPB_STATIC_SELECTOR_COUNT);
2646}
2647
2648const upb_msgdef *upb_handlers_msgdef(const upb_handlers *h) { return h->msg; }
2649
2650bool upb_handlers_addcleanup(upb_handlers *h, void *p, upb_handlerfree *func) {
Josh Habermane8ed0212015-06-08 17:56:03 -07002651 bool ok;
Chris Fallin91473dc2014-12-12 15:58:26 -08002652 if (upb_inttable_lookupptr(&h->cleanup_, p, NULL)) {
2653 return false;
2654 }
Josh Habermane8ed0212015-06-08 17:56:03 -07002655 ok = upb_inttable_insertptr(&h->cleanup_, p, upb_value_fptr(func));
Chris Fallin91473dc2014-12-12 15:58:26 -08002656 UPB_ASSERT_VAR(ok, ok);
2657 return true;
2658}
2659
2660
2661/* "Static" methods ***********************************************************/
2662
2663bool upb_handlers_freeze(upb_handlers *const*handlers, int n, upb_status *s) {
Josh Habermane8ed0212015-06-08 17:56:03 -07002664 /* TODO: verify we have a transitive closure. */
2665 int i;
2666 for (i = 0; i < n; i++) {
2667 upb_msg_field_iter j;
Chris Fallin91473dc2014-12-12 15:58:26 -08002668 upb_handlers *h = handlers[i];
2669
2670 if (!upb_ok(&h->status_)) {
2671 upb_status_seterrf(s, "handlers for message %s had error status: %s",
2672 upb_msgdef_fullname(upb_handlers_msgdef(h)),
2673 upb_status_errmsg(&h->status_));
2674 return false;
2675 }
2676
Josh Habermane8ed0212015-06-08 17:56:03 -07002677 /* Check that there are no closure mismatches due to missing Start* handlers
2678 * or subhandlers with different type-level types. */
Chris Fallinfcd88892015-01-13 18:14:39 -08002679 for(upb_msg_field_begin(&j, h->msg);
2680 !upb_msg_field_done(&j);
2681 upb_msg_field_next(&j)) {
Chris Fallin91473dc2014-12-12 15:58:26 -08002682
2683 const upb_fielddef *f = upb_msg_iter_field(&j);
2684 if (upb_fielddef_isseq(f)) {
2685 if (!checkstart(h, f, UPB_HANDLER_STARTSEQ, s))
2686 return false;
2687 }
2688
2689 if (upb_fielddef_isstring(f)) {
2690 if (!checkstart(h, f, UPB_HANDLER_STARTSTR, s))
2691 return false;
2692 }
2693
2694 if (upb_fielddef_issubmsg(f)) {
2695 bool hashandler = false;
2696 if (upb_handlers_gethandler(
2697 h, handlers_getsel(h, f, UPB_HANDLER_STARTSUBMSG)) ||
2698 upb_handlers_gethandler(
2699 h, handlers_getsel(h, f, UPB_HANDLER_ENDSUBMSG))) {
2700 hashandler = true;
2701 }
2702
2703 if (upb_fielddef_isseq(f) &&
2704 (upb_handlers_gethandler(
2705 h, handlers_getsel(h, f, UPB_HANDLER_STARTSEQ)) ||
2706 upb_handlers_gethandler(
2707 h, handlers_getsel(h, f, UPB_HANDLER_ENDSEQ)))) {
2708 hashandler = true;
2709 }
2710
2711 if (hashandler && !upb_handlers_getsubhandlers(h, f)) {
Josh Habermane8ed0212015-06-08 17:56:03 -07002712 /* For now we add an empty subhandlers in this case. It makes the
2713 * decoder code generator simpler, because it only has to handle two
2714 * cases (submessage has handlers or not) as opposed to three
2715 * (submessage has handlers in enclosing message but no subhandlers).
2716 *
2717 * This makes parsing less efficient in the case that we want to
2718 * notice a submessage but skip its contents (like if we're testing
2719 * for submessage presence or counting the number of repeated
2720 * submessages). In this case we will end up parsing the submessage
2721 * field by field and throwing away the results for each, instead of
2722 * skipping the whole delimited thing at once. If this is an issue we
2723 * can revisit it, but do remember that this only arises when you have
2724 * handlers (startseq/startsubmsg/endsubmsg/endseq) set for the
2725 * submessage but no subhandlers. The uses cases for this are
2726 * limited. */
Chris Fallin91473dc2014-12-12 15:58:26 -08002727 upb_handlers *sub = upb_handlers_new(upb_fielddef_msgsubdef(f), &sub);
2728 upb_handlers_setsubhandlers(h, f, sub);
2729 upb_handlers_unref(sub, &sub);
2730 }
2731
Josh Habermane8ed0212015-06-08 17:56:03 -07002732 /* TODO(haberman): check type of submessage.
2733 * This is slightly tricky; also consider whether we should check that
2734 * they match at setsubhandlers time. */
Chris Fallin91473dc2014-12-12 15:58:26 -08002735 }
2736 }
2737 }
2738
2739 if (!upb_refcounted_freeze((upb_refcounted*const*)handlers, n, s,
2740 UPB_MAX_HANDLER_DEPTH)) {
2741 return false;
2742 }
2743
2744 return true;
2745}
2746
2747upb_handlertype_t upb_handlers_getprimitivehandlertype(const upb_fielddef *f) {
2748 switch (upb_fielddef_type(f)) {
2749 case UPB_TYPE_INT32:
2750 case UPB_TYPE_ENUM: return UPB_HANDLER_INT32;
2751 case UPB_TYPE_INT64: return UPB_HANDLER_INT64;
2752 case UPB_TYPE_UINT32: return UPB_HANDLER_UINT32;
2753 case UPB_TYPE_UINT64: return UPB_HANDLER_UINT64;
2754 case UPB_TYPE_FLOAT: return UPB_HANDLER_FLOAT;
2755 case UPB_TYPE_DOUBLE: return UPB_HANDLER_DOUBLE;
2756 case UPB_TYPE_BOOL: return UPB_HANDLER_BOOL;
Josh Habermane8ed0212015-06-08 17:56:03 -07002757 default: assert(false); return -1; /* Invalid input. */
Chris Fallin91473dc2014-12-12 15:58:26 -08002758 }
2759}
2760
2761bool upb_handlers_getselector(const upb_fielddef *f, upb_handlertype_t type,
2762 upb_selector_t *s) {
2763 switch (type) {
2764 case UPB_HANDLER_INT32:
2765 case UPB_HANDLER_INT64:
2766 case UPB_HANDLER_UINT32:
2767 case UPB_HANDLER_UINT64:
2768 case UPB_HANDLER_FLOAT:
2769 case UPB_HANDLER_DOUBLE:
2770 case UPB_HANDLER_BOOL:
2771 if (!upb_fielddef_isprimitive(f) ||
2772 upb_handlers_getprimitivehandlertype(f) != type)
2773 return false;
2774 *s = f->selector_base;
2775 break;
2776 case UPB_HANDLER_STRING:
2777 if (upb_fielddef_isstring(f)) {
2778 *s = f->selector_base;
2779 } else if (upb_fielddef_lazy(f)) {
2780 *s = f->selector_base + 3;
2781 } else {
2782 return false;
2783 }
2784 break;
2785 case UPB_HANDLER_STARTSTR:
2786 if (upb_fielddef_isstring(f) || upb_fielddef_lazy(f)) {
2787 *s = f->selector_base + 1;
2788 } else {
2789 return false;
2790 }
2791 break;
2792 case UPB_HANDLER_ENDSTR:
2793 if (upb_fielddef_isstring(f) || upb_fielddef_lazy(f)) {
2794 *s = f->selector_base + 2;
2795 } else {
2796 return false;
2797 }
2798 break;
2799 case UPB_HANDLER_STARTSEQ:
2800 if (!upb_fielddef_isseq(f)) return false;
2801 *s = f->selector_base - 2;
2802 break;
2803 case UPB_HANDLER_ENDSEQ:
2804 if (!upb_fielddef_isseq(f)) return false;
2805 *s = f->selector_base - 1;
2806 break;
2807 case UPB_HANDLER_STARTSUBMSG:
2808 if (!upb_fielddef_issubmsg(f)) return false;
Josh Habermane8ed0212015-06-08 17:56:03 -07002809 /* Selectors for STARTSUBMSG are at the beginning of the table so that the
2810 * selector can also be used as an index into the "sub" array of
2811 * subhandlers. The indexes for the two into these two tables are the
2812 * same, except that in the handler table the static selectors come first. */
Chris Fallin91473dc2014-12-12 15:58:26 -08002813 *s = f->index_ + UPB_STATIC_SELECTOR_COUNT;
2814 break;
2815 case UPB_HANDLER_ENDSUBMSG:
2816 if (!upb_fielddef_issubmsg(f)) return false;
2817 *s = f->selector_base;
2818 break;
2819 }
Chris Fallind3262772015-05-14 18:24:26 -07002820 assert((size_t)*s < upb_fielddef_containingtype(f)->selector_count);
Chris Fallin91473dc2014-12-12 15:58:26 -08002821 return true;
2822}
2823
2824uint32_t upb_handlers_selectorbaseoffset(const upb_fielddef *f) {
2825 return upb_fielddef_isseq(f) ? 2 : 0;
2826}
2827
2828uint32_t upb_handlers_selectorcount(const upb_fielddef *f) {
2829 uint32_t ret = 1;
Josh Habermane8ed0212015-06-08 17:56:03 -07002830 if (upb_fielddef_isseq(f)) ret += 2; /* STARTSEQ/ENDSEQ */
2831 if (upb_fielddef_isstring(f)) ret += 2; /* [STRING]/STARTSTR/ENDSTR */
Chris Fallin91473dc2014-12-12 15:58:26 -08002832 if (upb_fielddef_issubmsg(f)) {
Josh Habermane8ed0212015-06-08 17:56:03 -07002833 /* ENDSUBMSG (STARTSUBMSG is at table beginning) */
Chris Fallin91473dc2014-12-12 15:58:26 -08002834 ret += 0;
2835 if (upb_fielddef_lazy(f)) {
Josh Habermane8ed0212015-06-08 17:56:03 -07002836 /* STARTSTR/ENDSTR/STRING (for lazy) */
Chris Fallin91473dc2014-12-12 15:58:26 -08002837 ret += 3;
2838 }
2839 }
2840 return ret;
2841}
2842
2843
2844/* upb_handlerattr ************************************************************/
2845
2846void upb_handlerattr_init(upb_handlerattr *attr) {
2847 upb_handlerattr from = UPB_HANDLERATTR_INITIALIZER;
2848 memcpy(attr, &from, sizeof(*attr));
2849}
2850
2851void upb_handlerattr_uninit(upb_handlerattr *attr) {
2852 UPB_UNUSED(attr);
2853}
2854
2855bool upb_handlerattr_sethandlerdata(upb_handlerattr *attr, const void *hd) {
2856 attr->handler_data_ = hd;
2857 return true;
2858}
2859
2860bool upb_handlerattr_setclosuretype(upb_handlerattr *attr, const void *type) {
2861 attr->closure_type_ = type;
2862 return true;
2863}
2864
2865const void *upb_handlerattr_closuretype(const upb_handlerattr *attr) {
2866 return attr->closure_type_;
2867}
2868
2869bool upb_handlerattr_setreturnclosuretype(upb_handlerattr *attr,
2870 const void *type) {
2871 attr->return_closure_type_ = type;
2872 return true;
2873}
2874
2875const void *upb_handlerattr_returnclosuretype(const upb_handlerattr *attr) {
2876 return attr->return_closure_type_;
2877}
2878
2879bool upb_handlerattr_setalwaysok(upb_handlerattr *attr, bool alwaysok) {
2880 attr->alwaysok_ = alwaysok;
2881 return true;
2882}
2883
2884bool upb_handlerattr_alwaysok(const upb_handlerattr *attr) {
2885 return attr->alwaysok_;
2886}
2887
2888/* upb_bufhandle **************************************************************/
2889
2890size_t upb_bufhandle_objofs(const upb_bufhandle *h) {
2891 return h->objofs_;
2892}
2893
2894/* upb_byteshandler ***********************************************************/
2895
2896void upb_byteshandler_init(upb_byteshandler* h) {
2897 memset(h, 0, sizeof(*h));
2898}
2899
Josh Habermane8ed0212015-06-08 17:56:03 -07002900/* For when we support handlerfree callbacks. */
Chris Fallin91473dc2014-12-12 15:58:26 -08002901void upb_byteshandler_uninit(upb_byteshandler* h) {
2902 UPB_UNUSED(h);
2903}
2904
2905bool upb_byteshandler_setstartstr(upb_byteshandler *h,
2906 upb_startstr_handlerfunc *func, void *d) {
2907 h->table[UPB_STARTSTR_SELECTOR].func = (upb_func*)func;
2908 h->table[UPB_STARTSTR_SELECTOR].attr.handler_data_ = d;
2909 return true;
2910}
2911
2912bool upb_byteshandler_setstring(upb_byteshandler *h,
2913 upb_string_handlerfunc *func, void *d) {
2914 h->table[UPB_STRING_SELECTOR].func = (upb_func*)func;
2915 h->table[UPB_STRING_SELECTOR].attr.handler_data_ = d;
2916 return true;
2917}
2918
2919bool upb_byteshandler_setendstr(upb_byteshandler *h,
2920 upb_endfield_handlerfunc *func, void *d) {
2921 h->table[UPB_ENDSTR_SELECTOR].func = (upb_func*)func;
2922 h->table[UPB_ENDSTR_SELECTOR].attr.handler_data_ = d;
2923 return true;
2924}
2925/*
Josh Haberman181c7f22015-07-15 11:05:10 -07002926** upb::RefCounted Implementation
2927**
2928** Our key invariants are:
2929** 1. reference cycles never span groups
2930** 2. for ref2(to, from), we increment to's count iff group(from) != group(to)
2931**
2932** The previous two are how we avoid leaking cycles. Other important
2933** invariants are:
2934** 3. for mutable objects "from" and "to", if there exists a ref2(to, from)
2935** this implies group(from) == group(to). (In practice, what we implement
2936** is even stronger; "from" and "to" will share a group if there has *ever*
2937** been a ref2(to, from), but all that is necessary for correctness is the
2938** weaker one).
2939** 4. mutable and immutable objects are never in the same group.
2940*/
Chris Fallin91473dc2014-12-12 15:58:26 -08002941
2942
2943#include <setjmp.h>
2944#include <stdlib.h>
2945
2946static void freeobj(upb_refcounted *o);
2947
2948const char untracked_val;
2949const void *UPB_UNTRACKED_REF = &untracked_val;
2950
2951/* arch-specific atomic primitives *******************************************/
2952
Josh Habermane8ed0212015-06-08 17:56:03 -07002953#ifdef UPB_THREAD_UNSAFE /*---------------------------------------------------*/
Chris Fallin91473dc2014-12-12 15:58:26 -08002954
2955static void atomic_inc(uint32_t *a) { (*a)++; }
2956static bool atomic_dec(uint32_t *a) { return --(*a) == 0; }
2957
Josh Habermane8ed0212015-06-08 17:56:03 -07002958#elif defined(__GNUC__) || defined(__clang__) /*------------------------------*/
Chris Fallin91473dc2014-12-12 15:58:26 -08002959
2960static void atomic_inc(uint32_t *a) { __sync_fetch_and_add(a, 1); }
2961static bool atomic_dec(uint32_t *a) { return __sync_sub_and_fetch(a, 1) == 0; }
2962
Josh Habermane8ed0212015-06-08 17:56:03 -07002963#elif defined(WIN32) /*-------------------------------------------------------*/
Chris Fallin91473dc2014-12-12 15:58:26 -08002964
2965#include <Windows.h>
2966
2967static void atomic_inc(upb_atomic_t *a) { InterlockedIncrement(&a->val); }
2968static bool atomic_dec(upb_atomic_t *a) {
2969 return InterlockedDecrement(&a->val) == 0;
2970}
2971
2972#else
2973#error Atomic primitives not defined for your platform/CPU. \
2974 Implement them or compile with UPB_THREAD_UNSAFE.
2975#endif
2976
Josh Habermane8ed0212015-06-08 17:56:03 -07002977/* All static objects point to this refcount.
2978 * It is special-cased in ref/unref below. */
Chris Fallin91473dc2014-12-12 15:58:26 -08002979uint32_t static_refcount = -1;
2980
Josh Habermane8ed0212015-06-08 17:56:03 -07002981/* We can avoid atomic ops for statically-declared objects.
2982 * This is a minor optimization but nice since we can avoid degrading under
2983 * contention in this case. */
Chris Fallin91473dc2014-12-12 15:58:26 -08002984
2985static void refgroup(uint32_t *group) {
2986 if (group != &static_refcount)
2987 atomic_inc(group);
2988}
2989
2990static bool unrefgroup(uint32_t *group) {
2991 if (group == &static_refcount) {
2992 return false;
2993 } else {
2994 return atomic_dec(group);
2995 }
2996}
2997
2998
2999/* Reference tracking (debug only) ********************************************/
3000
3001#ifdef UPB_DEBUG_REFS
3002
3003#ifdef UPB_THREAD_UNSAFE
3004
3005static void upb_lock() {}
3006static void upb_unlock() {}
3007
3008#else
3009
Josh Habermane8ed0212015-06-08 17:56:03 -07003010/* User must define functions that lock/unlock a global mutex and link this
3011 * file against them. */
Chris Fallin91473dc2014-12-12 15:58:26 -08003012void upb_lock();
3013void upb_unlock();
3014
3015#endif
3016
Josh Habermane8ed0212015-06-08 17:56:03 -07003017/* UPB_DEBUG_REFS mode counts on being able to malloc() memory in some
3018 * code-paths that can normally never fail, like upb_refcounted_ref(). Since
3019 * we have no way to propagage out-of-memory errors back to the user, and since
3020 * these errors can only occur in UPB_DEBUG_REFS mode, we immediately fail. */
Chris Fallin91473dc2014-12-12 15:58:26 -08003021#define CHECK_OOM(predicate) if (!(predicate)) { assert(predicate); exit(1); }
3022
3023typedef struct {
Josh Habermane8ed0212015-06-08 17:56:03 -07003024 int count; /* How many refs there are (duplicates only allowed for ref2). */
Chris Fallin91473dc2014-12-12 15:58:26 -08003025 bool is_ref2;
3026} trackedref;
3027
3028static trackedref *trackedref_new(bool is_ref2) {
3029 trackedref *ret = malloc(sizeof(*ret));
3030 CHECK_OOM(ret);
3031 ret->count = 1;
3032 ret->is_ref2 = is_ref2;
3033 return ret;
3034}
3035
3036static void track(const upb_refcounted *r, const void *owner, bool ref2) {
Josh Habermane8ed0212015-06-08 17:56:03 -07003037 upb_value v;
3038
Chris Fallin91473dc2014-12-12 15:58:26 -08003039 assert(owner);
3040 if (owner == UPB_UNTRACKED_REF) return;
3041
3042 upb_lock();
Chris Fallin91473dc2014-12-12 15:58:26 -08003043 if (upb_inttable_lookupptr(r->refs, owner, &v)) {
3044 trackedref *ref = upb_value_getptr(v);
Josh Habermane8ed0212015-06-08 17:56:03 -07003045 /* Since we allow multiple ref2's for the same to/from pair without
3046 * allocating separate memory for each one, we lose the fine-grained
3047 * tracking behavior we get with regular refs. Since ref2s only happen
3048 * inside upb, we'll accept this limitation until/unless there is a really
3049 * difficult upb-internal bug that can't be figured out without it. */
Chris Fallin91473dc2014-12-12 15:58:26 -08003050 assert(ref2);
3051 assert(ref->is_ref2);
3052 ref->count++;
3053 } else {
3054 trackedref *ref = trackedref_new(ref2);
3055 bool ok = upb_inttable_insertptr(r->refs, owner, upb_value_ptr(ref));
3056 CHECK_OOM(ok);
3057 if (ref2) {
Josh Habermane8ed0212015-06-08 17:56:03 -07003058 /* We know this cast is safe when it is a ref2, because it's coming from
3059 * another refcounted object. */
Chris Fallin91473dc2014-12-12 15:58:26 -08003060 const upb_refcounted *from = owner;
3061 assert(!upb_inttable_lookupptr(from->ref2s, r, NULL));
3062 ok = upb_inttable_insertptr(from->ref2s, r, upb_value_ptr(NULL));
3063 CHECK_OOM(ok);
3064 }
3065 }
3066 upb_unlock();
3067}
3068
3069static void untrack(const upb_refcounted *r, const void *owner, bool ref2) {
Josh Habermane8ed0212015-06-08 17:56:03 -07003070 upb_value v;
3071 bool found;
3072 trackedref *ref;
3073
Chris Fallin91473dc2014-12-12 15:58:26 -08003074 assert(owner);
3075 if (owner == UPB_UNTRACKED_REF) return;
3076
3077 upb_lock();
Josh Habermane8ed0212015-06-08 17:56:03 -07003078 found = upb_inttable_lookupptr(r->refs, owner, &v);
3079 /* This assert will fail if an owner attempts to release a ref it didn't have. */
Chris Fallin91473dc2014-12-12 15:58:26 -08003080 UPB_ASSERT_VAR(found, found);
Josh Habermane8ed0212015-06-08 17:56:03 -07003081 ref = upb_value_getptr(v);
Chris Fallin91473dc2014-12-12 15:58:26 -08003082 assert(ref->is_ref2 == ref2);
3083 if (--ref->count == 0) {
3084 free(ref);
3085 upb_inttable_removeptr(r->refs, owner, NULL);
3086 if (ref2) {
Josh Habermane8ed0212015-06-08 17:56:03 -07003087 /* We know this cast is safe when it is a ref2, because it's coming from
3088 * another refcounted object. */
Chris Fallin91473dc2014-12-12 15:58:26 -08003089 const upb_refcounted *from = owner;
3090 bool removed = upb_inttable_removeptr(from->ref2s, r, NULL);
3091 assert(removed);
3092 }
3093 }
3094 upb_unlock();
3095}
3096
3097static void checkref(const upb_refcounted *r, const void *owner, bool ref2) {
Chris Fallin91473dc2014-12-12 15:58:26 -08003098 upb_value v;
Josh Habermane8ed0212015-06-08 17:56:03 -07003099 bool found;
3100 trackedref *ref;
3101
3102 upb_lock();
3103 found = upb_inttable_lookupptr(r->refs, owner, &v);
Chris Fallin91473dc2014-12-12 15:58:26 -08003104 UPB_ASSERT_VAR(found, found);
Josh Habermane8ed0212015-06-08 17:56:03 -07003105 ref = upb_value_getptr(v);
Chris Fallin91473dc2014-12-12 15:58:26 -08003106 assert(ref->is_ref2 == ref2);
3107 upb_unlock();
3108}
3109
Josh Habermane8ed0212015-06-08 17:56:03 -07003110/* Populates the given UPB_CTYPE_INT32 inttable with counts of ref2's that
3111 * originate from the given owner. */
Chris Fallin91473dc2014-12-12 15:58:26 -08003112static void getref2s(const upb_refcounted *owner, upb_inttable *tab) {
Chris Fallin91473dc2014-12-12 15:58:26 -08003113 upb_inttable_iter i;
Josh Habermane8ed0212015-06-08 17:56:03 -07003114
3115 upb_lock();
Chris Fallin91473dc2014-12-12 15:58:26 -08003116 upb_inttable_begin(&i, owner->ref2s);
3117 for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
Josh Habermane8ed0212015-06-08 17:56:03 -07003118 upb_value v;
3119 upb_value count;
3120 trackedref *ref;
3121 bool ok;
3122 bool found;
3123
Chris Fallin91473dc2014-12-12 15:58:26 -08003124 upb_refcounted *to = (upb_refcounted*)upb_inttable_iter_key(&i);
3125
Josh Habermane8ed0212015-06-08 17:56:03 -07003126 /* To get the count we need to look in the target's table. */
3127 found = upb_inttable_lookupptr(to->refs, owner, &v);
Chris Fallin91473dc2014-12-12 15:58:26 -08003128 assert(found);
Josh Habermane8ed0212015-06-08 17:56:03 -07003129 ref = upb_value_getptr(v);
3130 count = upb_value_int32(ref->count);
Chris Fallin91473dc2014-12-12 15:58:26 -08003131
Josh Habermane8ed0212015-06-08 17:56:03 -07003132 ok = upb_inttable_insertptr(tab, to, count);
Chris Fallin91473dc2014-12-12 15:58:26 -08003133 CHECK_OOM(ok);
3134 }
3135 upb_unlock();
3136}
3137
3138typedef struct {
3139 upb_inttable ref2;
3140 const upb_refcounted *obj;
3141} check_state;
3142
3143static void visit_check(const upb_refcounted *obj, const upb_refcounted *subobj,
3144 void *closure) {
3145 check_state *s = closure;
Chris Fallin91473dc2014-12-12 15:58:26 -08003146 upb_inttable *ref2 = &s->ref2;
3147 upb_value v;
Josh Habermane8ed0212015-06-08 17:56:03 -07003148 bool removed;
3149 int32_t newcount;
3150
3151 assert(obj == s->obj);
3152 assert(subobj);
3153 removed = upb_inttable_removeptr(ref2, subobj, &v);
3154 /* The following assertion will fail if the visit() function visits a subobj
3155 * that it did not have a ref2 on, or visits the same subobj too many times. */
Chris Fallin91473dc2014-12-12 15:58:26 -08003156 assert(removed);
Josh Habermane8ed0212015-06-08 17:56:03 -07003157 newcount = upb_value_getint32(v) - 1;
Chris Fallin91473dc2014-12-12 15:58:26 -08003158 if (newcount > 0) {
3159 upb_inttable_insert(ref2, (uintptr_t)subobj, upb_value_int32(newcount));
3160 }
3161}
3162
3163static void visit(const upb_refcounted *r, upb_refcounted_visit *v,
3164 void *closure) {
Josh Habermane8ed0212015-06-08 17:56:03 -07003165 bool ok;
3166
3167 /* In DEBUG_REFS mode we know what existing ref2 refs there are, so we know
3168 * exactly the set of nodes that visit() should visit. So we verify visit()'s
3169 * correctness here. */
Chris Fallin91473dc2014-12-12 15:58:26 -08003170 check_state state;
3171 state.obj = r;
Josh Habermane8ed0212015-06-08 17:56:03 -07003172 ok = upb_inttable_init(&state.ref2, UPB_CTYPE_INT32);
Chris Fallin91473dc2014-12-12 15:58:26 -08003173 CHECK_OOM(ok);
3174 getref2s(r, &state.ref2);
3175
Josh Habermane8ed0212015-06-08 17:56:03 -07003176 /* This should visit any children in the ref2 table. */
Chris Fallin91473dc2014-12-12 15:58:26 -08003177 if (r->vtbl->visit) r->vtbl->visit(r, visit_check, &state);
3178
Josh Habermane8ed0212015-06-08 17:56:03 -07003179 /* This assertion will fail if the visit() function missed any children. */
Chris Fallin91473dc2014-12-12 15:58:26 -08003180 assert(upb_inttable_count(&state.ref2) == 0);
3181 upb_inttable_uninit(&state.ref2);
3182 if (r->vtbl->visit) r->vtbl->visit(r, v, closure);
3183}
3184
3185static bool trackinit(upb_refcounted *r) {
3186 r->refs = malloc(sizeof(*r->refs));
3187 r->ref2s = malloc(sizeof(*r->ref2s));
3188 if (!r->refs || !r->ref2s) goto err1;
3189
3190 if (!upb_inttable_init(r->refs, UPB_CTYPE_PTR)) goto err1;
3191 if (!upb_inttable_init(r->ref2s, UPB_CTYPE_PTR)) goto err2;
3192 return true;
3193
3194err2:
3195 upb_inttable_uninit(r->refs);
3196err1:
3197 free(r->refs);
3198 free(r->ref2s);
3199 return false;
3200}
3201
3202static void trackfree(const upb_refcounted *r) {
3203 upb_inttable_uninit(r->refs);
3204 upb_inttable_uninit(r->ref2s);
3205 free(r->refs);
3206 free(r->ref2s);
3207}
3208
3209#else
3210
3211static void track(const upb_refcounted *r, const void *owner, bool ref2) {
3212 UPB_UNUSED(r);
3213 UPB_UNUSED(owner);
3214 UPB_UNUSED(ref2);
3215}
3216
3217static void untrack(const upb_refcounted *r, const void *owner, bool ref2) {
3218 UPB_UNUSED(r);
3219 UPB_UNUSED(owner);
3220 UPB_UNUSED(ref2);
3221}
3222
3223static void checkref(const upb_refcounted *r, const void *owner, bool ref2) {
3224 UPB_UNUSED(r);
3225 UPB_UNUSED(owner);
3226 UPB_UNUSED(ref2);
3227}
3228
3229static bool trackinit(upb_refcounted *r) {
3230 UPB_UNUSED(r);
3231 return true;
3232}
3233
3234static void trackfree(const upb_refcounted *r) {
3235 UPB_UNUSED(r);
3236}
3237
3238static void visit(const upb_refcounted *r, upb_refcounted_visit *v,
3239 void *closure) {
3240 if (r->vtbl->visit) r->vtbl->visit(r, v, closure);
3241}
3242
Josh Habermane8ed0212015-06-08 17:56:03 -07003243#endif /* UPB_DEBUG_REFS */
Chris Fallin91473dc2014-12-12 15:58:26 -08003244
3245
3246/* freeze() *******************************************************************/
3247
Josh Habermane8ed0212015-06-08 17:56:03 -07003248/* The freeze() operation is by far the most complicated part of this scheme.
3249 * We compute strongly-connected components and then mutate the graph such that
3250 * we preserve the invariants documented at the top of this file. And we must
3251 * handle out-of-memory errors gracefully (without leaving the graph
3252 * inconsistent), which adds to the fun. */
Chris Fallin91473dc2014-12-12 15:58:26 -08003253
Josh Habermane8ed0212015-06-08 17:56:03 -07003254/* The state used by the freeze operation (shared across many functions). */
Chris Fallin91473dc2014-12-12 15:58:26 -08003255typedef struct {
3256 int depth;
3257 int maxdepth;
3258 uint64_t index;
Josh Habermane8ed0212015-06-08 17:56:03 -07003259 /* Maps upb_refcounted* -> attributes (color, etc). attr layout varies by
3260 * color. */
Chris Fallin91473dc2014-12-12 15:58:26 -08003261 upb_inttable objattr;
Josh Habermane8ed0212015-06-08 17:56:03 -07003262 upb_inttable stack; /* stack of upb_refcounted* for Tarjan's algorithm. */
3263 upb_inttable groups; /* array of uint32_t*, malloc'd refcounts for new groups */
Chris Fallin91473dc2014-12-12 15:58:26 -08003264 upb_status *status;
3265 jmp_buf err;
3266} tarjan;
3267
3268static void release_ref2(const upb_refcounted *obj,
3269 const upb_refcounted *subobj,
3270 void *closure);
3271
Josh Habermane8ed0212015-06-08 17:56:03 -07003272/* Node attributes -----------------------------------------------------------*/
Chris Fallin91473dc2014-12-12 15:58:26 -08003273
Josh Habermane8ed0212015-06-08 17:56:03 -07003274/* After our analysis phase all nodes will be either GRAY or WHITE. */
Chris Fallin91473dc2014-12-12 15:58:26 -08003275
3276typedef enum {
Josh Habermane8ed0212015-06-08 17:56:03 -07003277 BLACK = 0, /* Object has not been seen. */
3278 GRAY, /* Object has been found via a refgroup but may not be reachable. */
3279 GREEN, /* Object is reachable and is currently on the Tarjan stack. */
3280 WHITE /* Object is reachable and has been assigned a group (SCC). */
Chris Fallin91473dc2014-12-12 15:58:26 -08003281} color_t;
3282
3283UPB_NORETURN static void err(tarjan *t) { longjmp(t->err, 1); }
3284UPB_NORETURN static void oom(tarjan *t) {
3285 upb_status_seterrmsg(t->status, "out of memory");
3286 err(t);
3287}
3288
3289static uint64_t trygetattr(const tarjan *t, const upb_refcounted *r) {
3290 upb_value v;
3291 return upb_inttable_lookupptr(&t->objattr, r, &v) ?
3292 upb_value_getuint64(v) : 0;
3293}
3294
3295static uint64_t getattr(const tarjan *t, const upb_refcounted *r) {
3296 upb_value v;
3297 bool found = upb_inttable_lookupptr(&t->objattr, r, &v);
3298 UPB_ASSERT_VAR(found, found);
3299 return upb_value_getuint64(v);
3300}
3301
3302static void setattr(tarjan *t, const upb_refcounted *r, uint64_t attr) {
3303 upb_inttable_removeptr(&t->objattr, r, NULL);
3304 upb_inttable_insertptr(&t->objattr, r, upb_value_uint64(attr));
3305}
3306
3307static color_t color(tarjan *t, const upb_refcounted *r) {
Josh Habermane8ed0212015-06-08 17:56:03 -07003308 return trygetattr(t, r) & 0x3; /* Color is always stored in the low 2 bits. */
Chris Fallin91473dc2014-12-12 15:58:26 -08003309}
3310
3311static void set_gray(tarjan *t, const upb_refcounted *r) {
3312 assert(color(t, r) == BLACK);
3313 setattr(t, r, GRAY);
3314}
3315
Josh Habermane8ed0212015-06-08 17:56:03 -07003316/* Pushes an obj onto the Tarjan stack and sets it to GREEN. */
Chris Fallin91473dc2014-12-12 15:58:26 -08003317static void push(tarjan *t, const upb_refcounted *r) {
3318 assert(color(t, r) == BLACK || color(t, r) == GRAY);
Josh Habermane8ed0212015-06-08 17:56:03 -07003319 /* This defines the attr layout for the GREEN state. "index" and "lowlink"
3320 * get 31 bits, which is plenty (limit of 2B objects frozen at a time). */
Chris Fallin91473dc2014-12-12 15:58:26 -08003321 setattr(t, r, GREEN | (t->index << 2) | (t->index << 33));
3322 if (++t->index == 0x80000000) {
3323 upb_status_seterrmsg(t->status, "too many objects to freeze");
3324 err(t);
3325 }
3326 upb_inttable_push(&t->stack, upb_value_ptr((void*)r));
3327}
3328
Josh Habermane8ed0212015-06-08 17:56:03 -07003329/* Pops an obj from the Tarjan stack and sets it to WHITE, with a ptr to its
3330 * SCC group. */
Chris Fallin91473dc2014-12-12 15:58:26 -08003331static upb_refcounted *pop(tarjan *t) {
3332 upb_refcounted *r = upb_value_getptr(upb_inttable_pop(&t->stack));
3333 assert(color(t, r) == GREEN);
Josh Habermane8ed0212015-06-08 17:56:03 -07003334 /* This defines the attr layout for nodes in the WHITE state.
3335 * Top of group stack is [group, NULL]; we point at group. */
Chris Fallin91473dc2014-12-12 15:58:26 -08003336 setattr(t, r, WHITE | (upb_inttable_count(&t->groups) - 2) << 8);
3337 return r;
3338}
3339
3340static void tarjan_newgroup(tarjan *t) {
3341 uint32_t *group = malloc(sizeof(*group));
3342 if (!group) oom(t);
Josh Habermane8ed0212015-06-08 17:56:03 -07003343 /* Push group and empty group leader (we'll fill in leader later). */
Chris Fallin91473dc2014-12-12 15:58:26 -08003344 if (!upb_inttable_push(&t->groups, upb_value_ptr(group)) ||
3345 !upb_inttable_push(&t->groups, upb_value_ptr(NULL))) {
3346 free(group);
3347 oom(t);
3348 }
3349 *group = 0;
3350}
3351
3352static uint32_t idx(tarjan *t, const upb_refcounted *r) {
3353 assert(color(t, r) == GREEN);
3354 return (getattr(t, r) >> 2) & 0x7FFFFFFF;
3355}
3356
3357static uint32_t lowlink(tarjan *t, const upb_refcounted *r) {
3358 if (color(t, r) == GREEN) {
3359 return getattr(t, r) >> 33;
3360 } else {
3361 return UINT32_MAX;
3362 }
3363}
3364
3365static void set_lowlink(tarjan *t, const upb_refcounted *r, uint32_t lowlink) {
3366 assert(color(t, r) == GREEN);
3367 setattr(t, r, ((uint64_t)lowlink << 33) | (getattr(t, r) & 0x1FFFFFFFF));
3368}
3369
3370static uint32_t *group(tarjan *t, upb_refcounted *r) {
Josh Habermane8ed0212015-06-08 17:56:03 -07003371 uint64_t groupnum;
Chris Fallin91473dc2014-12-12 15:58:26 -08003372 upb_value v;
Josh Habermane8ed0212015-06-08 17:56:03 -07003373 bool found;
3374
3375 assert(color(t, r) == WHITE);
3376 groupnum = getattr(t, r) >> 8;
3377 found = upb_inttable_lookup(&t->groups, groupnum, &v);
Chris Fallin91473dc2014-12-12 15:58:26 -08003378 UPB_ASSERT_VAR(found, found);
3379 return upb_value_getptr(v);
3380}
3381
Josh Habermane8ed0212015-06-08 17:56:03 -07003382/* If the group leader for this object's group has not previously been set,
3383 * the given object is assigned to be its leader. */
Chris Fallin91473dc2014-12-12 15:58:26 -08003384static upb_refcounted *groupleader(tarjan *t, upb_refcounted *r) {
Josh Habermane8ed0212015-06-08 17:56:03 -07003385 uint64_t leader_slot;
Chris Fallin91473dc2014-12-12 15:58:26 -08003386 upb_value v;
Josh Habermane8ed0212015-06-08 17:56:03 -07003387 bool found;
3388
3389 assert(color(t, r) == WHITE);
3390 leader_slot = (getattr(t, r) >> 8) + 1;
3391 found = upb_inttable_lookup(&t->groups, leader_slot, &v);
Chris Fallin91473dc2014-12-12 15:58:26 -08003392 UPB_ASSERT_VAR(found, found);
3393 if (upb_value_getptr(v)) {
3394 return upb_value_getptr(v);
3395 } else {
3396 upb_inttable_remove(&t->groups, leader_slot, NULL);
3397 upb_inttable_insert(&t->groups, leader_slot, upb_value_ptr(r));
3398 return r;
3399 }
3400}
3401
3402
Josh Habermane8ed0212015-06-08 17:56:03 -07003403/* Tarjan's algorithm --------------------------------------------------------*/
Chris Fallin91473dc2014-12-12 15:58:26 -08003404
Josh Habermane8ed0212015-06-08 17:56:03 -07003405/* See:
3406 * http://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm */
Chris Fallin91473dc2014-12-12 15:58:26 -08003407static void do_tarjan(const upb_refcounted *obj, tarjan *t);
3408
3409static void tarjan_visit(const upb_refcounted *obj,
3410 const upb_refcounted *subobj,
3411 void *closure) {
3412 tarjan *t = closure;
3413 if (++t->depth > t->maxdepth) {
3414 upb_status_seterrf(t->status, "graph too deep to freeze (%d)", t->maxdepth);
3415 err(t);
3416 } else if (subobj->is_frozen || color(t, subobj) == WHITE) {
Josh Habermane8ed0212015-06-08 17:56:03 -07003417 /* Do nothing: we don't want to visit or color already-frozen nodes,
3418 * and WHITE nodes have already been assigned a SCC. */
Chris Fallin91473dc2014-12-12 15:58:26 -08003419 } else if (color(t, subobj) < GREEN) {
Josh Habermane8ed0212015-06-08 17:56:03 -07003420 /* Subdef has not yet been visited; recurse on it. */
Chris Fallin91473dc2014-12-12 15:58:26 -08003421 do_tarjan(subobj, t);
3422 set_lowlink(t, obj, UPB_MIN(lowlink(t, obj), lowlink(t, subobj)));
3423 } else if (color(t, subobj) == GREEN) {
Josh Habermane8ed0212015-06-08 17:56:03 -07003424 /* Subdef is in the stack and hence in the current SCC. */
Chris Fallin91473dc2014-12-12 15:58:26 -08003425 set_lowlink(t, obj, UPB_MIN(lowlink(t, obj), idx(t, subobj)));
3426 }
3427 --t->depth;
3428}
3429
3430static void do_tarjan(const upb_refcounted *obj, tarjan *t) {
3431 if (color(t, obj) == BLACK) {
Josh Habermane8ed0212015-06-08 17:56:03 -07003432 /* We haven't seen this object's group; mark the whole group GRAY. */
Chris Fallin91473dc2014-12-12 15:58:26 -08003433 const upb_refcounted *o = obj;
3434 do { set_gray(t, o); } while ((o = o->next) != obj);
3435 }
3436
3437 push(t, obj);
3438 visit(obj, tarjan_visit, t);
3439 if (lowlink(t, obj) == idx(t, obj)) {
3440 tarjan_newgroup(t);
3441 while (pop(t) != obj)
3442 ;
3443 }
3444}
3445
3446
Josh Habermane8ed0212015-06-08 17:56:03 -07003447/* freeze() ------------------------------------------------------------------*/
Chris Fallin91473dc2014-12-12 15:58:26 -08003448
3449static void crossref(const upb_refcounted *r, const upb_refcounted *subobj,
3450 void *_t) {
3451 tarjan *t = _t;
3452 assert(color(t, r) > BLACK);
3453 if (color(t, subobj) > BLACK && r->group != subobj->group) {
Josh Habermane8ed0212015-06-08 17:56:03 -07003454 /* Previously this ref was not reflected in subobj->group because they
3455 * were in the same group; now that they are split a ref must be taken. */
Chris Fallin91473dc2014-12-12 15:58:26 -08003456 refgroup(subobj->group);
3457 }
3458}
3459
3460static bool freeze(upb_refcounted *const*roots, int n, upb_status *s,
3461 int maxdepth) {
3462 volatile bool ret = false;
Josh Habermane8ed0212015-06-08 17:56:03 -07003463 int i;
3464 upb_inttable_iter iter;
Chris Fallin91473dc2014-12-12 15:58:26 -08003465
Josh Habermane8ed0212015-06-08 17:56:03 -07003466 /* We run in two passes so that we can allocate all memory before performing
3467 * any mutation of the input -- this allows us to leave the input unchanged
3468 * in the case of memory allocation failure. */
Chris Fallin91473dc2014-12-12 15:58:26 -08003469 tarjan t;
3470 t.index = 0;
3471 t.depth = 0;
3472 t.maxdepth = maxdepth;
3473 t.status = s;
3474 if (!upb_inttable_init(&t.objattr, UPB_CTYPE_UINT64)) goto err1;
3475 if (!upb_inttable_init(&t.stack, UPB_CTYPE_PTR)) goto err2;
3476 if (!upb_inttable_init(&t.groups, UPB_CTYPE_PTR)) goto err3;
3477 if (setjmp(t.err) != 0) goto err4;
3478
3479
Josh Habermane8ed0212015-06-08 17:56:03 -07003480 for (i = 0; i < n; i++) {
Chris Fallin91473dc2014-12-12 15:58:26 -08003481 if (color(&t, roots[i]) < GREEN) {
3482 do_tarjan(roots[i], &t);
3483 }
3484 }
3485
Josh Habermane8ed0212015-06-08 17:56:03 -07003486 /* If we've made it this far, no further errors are possible so it's safe to
3487 * mutate the objects without risk of leaving them in an inconsistent state. */
Chris Fallin91473dc2014-12-12 15:58:26 -08003488 ret = true;
3489
Josh Habermane8ed0212015-06-08 17:56:03 -07003490 /* The transformation that follows requires care. The preconditions are:
3491 * - all objects in attr map are WHITE or GRAY, and are in mutable groups
3492 * (groups of all mutable objs)
3493 * - no ref2(to, from) refs have incremented count(to) if both "to" and
3494 * "from" are in our attr map (this follows from invariants (2) and (3)) */
Chris Fallin91473dc2014-12-12 15:58:26 -08003495
Josh Habermane8ed0212015-06-08 17:56:03 -07003496 /* Pass 1: we remove WHITE objects from their mutable groups, and add them to
3497 * new groups according to the SCC's we computed. These new groups will
3498 * consist of only frozen objects. None will be immediately collectible,
3499 * because WHITE objects are by definition reachable from one of "roots",
3500 * which the caller must own refs on. */
3501 upb_inttable_begin(&iter, &t.objattr);
3502 for(; !upb_inttable_done(&iter); upb_inttable_next(&iter)) {
3503 upb_refcounted *obj = (upb_refcounted*)upb_inttable_iter_key(&iter);
3504 /* Since removal from a singly-linked list requires access to the object's
3505 * predecessor, we consider obj->next instead of obj for moving. With the
3506 * while() loop we guarantee that we will visit every node's predecessor.
3507 * Proof:
3508 * 1. every node's predecessor is in our attr map.
3509 * 2. though the loop body may change a node's predecessor, it will only
3510 * change it to be the node we are currently operating on, so with a
3511 * while() loop we guarantee ourselves the chance to remove each node. */
Chris Fallin91473dc2014-12-12 15:58:26 -08003512 while (color(&t, obj->next) == WHITE &&
3513 group(&t, obj->next) != obj->next->group) {
Josh Habermane8ed0212015-06-08 17:56:03 -07003514 upb_refcounted *leader;
3515
3516 /* Remove from old group. */
Chris Fallin91473dc2014-12-12 15:58:26 -08003517 upb_refcounted *move = obj->next;
3518 if (obj == move) {
Josh Habermane8ed0212015-06-08 17:56:03 -07003519 /* Removing the last object from a group. */
Chris Fallin91473dc2014-12-12 15:58:26 -08003520 assert(*obj->group == obj->individual_count);
3521 free(obj->group);
3522 } else {
3523 obj->next = move->next;
Josh Habermane8ed0212015-06-08 17:56:03 -07003524 /* This may decrease to zero; we'll collect GRAY objects (if any) that
3525 * remain in the group in the third pass. */
Chris Fallin91473dc2014-12-12 15:58:26 -08003526 assert(*move->group >= move->individual_count);
3527 *move->group -= move->individual_count;
3528 }
3529
Josh Habermane8ed0212015-06-08 17:56:03 -07003530 /* Add to new group. */
3531 leader = groupleader(&t, move);
Chris Fallin91473dc2014-12-12 15:58:26 -08003532 if (move == leader) {
Josh Habermane8ed0212015-06-08 17:56:03 -07003533 /* First object added to new group is its leader. */
Chris Fallin91473dc2014-12-12 15:58:26 -08003534 move->group = group(&t, move);
3535 move->next = move;
3536 *move->group = move->individual_count;
3537 } else {
Josh Habermane8ed0212015-06-08 17:56:03 -07003538 /* Group already has at least one object in it. */
Chris Fallin91473dc2014-12-12 15:58:26 -08003539 assert(leader->group == group(&t, move));
3540 move->group = group(&t, move);
3541 move->next = leader->next;
3542 leader->next = move;
3543 *move->group += move->individual_count;
3544 }
3545
3546 move->is_frozen = true;
3547 }
3548 }
3549
Josh Habermane8ed0212015-06-08 17:56:03 -07003550 /* Pass 2: GRAY and WHITE objects "obj" with ref2(to, obj) references must
3551 * increment count(to) if group(obj) != group(to) (which could now be the
3552 * case if "to" was just frozen). */
3553 upb_inttable_begin(&iter, &t.objattr);
3554 for(; !upb_inttable_done(&iter); upb_inttable_next(&iter)) {
3555 upb_refcounted *obj = (upb_refcounted*)upb_inttable_iter_key(&iter);
Chris Fallin91473dc2014-12-12 15:58:26 -08003556 visit(obj, crossref, &t);
3557 }
3558
Josh Habermane8ed0212015-06-08 17:56:03 -07003559 /* Pass 3: GRAY objects are collected if their group's refcount dropped to
3560 * zero when we removed its white nodes. This can happen if they had only
3561 * been kept alive by virtue of sharing a group with an object that was just
3562 * frozen.
3563 *
3564 * It is important that we do this last, since the GRAY object's free()
3565 * function could call unref2() on just-frozen objects, which will decrement
3566 * refs that were added in pass 2. */
3567 upb_inttable_begin(&iter, &t.objattr);
3568 for(; !upb_inttable_done(&iter); upb_inttable_next(&iter)) {
3569 upb_refcounted *obj = (upb_refcounted*)upb_inttable_iter_key(&iter);
Chris Fallin91473dc2014-12-12 15:58:26 -08003570 if (obj->group == NULL || *obj->group == 0) {
3571 if (obj->group) {
Josh Habermane8ed0212015-06-08 17:56:03 -07003572 upb_refcounted *o;
3573
3574 /* We eagerly free() the group's count (since we can't easily determine
3575 * the group's remaining size it's the easiest way to ensure it gets
3576 * done). */
Chris Fallin91473dc2014-12-12 15:58:26 -08003577 free(obj->group);
3578
Josh Habermane8ed0212015-06-08 17:56:03 -07003579 /* Visit to release ref2's (done in a separate pass since release_ref2
3580 * depends on o->group being unmodified so it can test merged()). */
3581 o = obj;
Chris Fallin91473dc2014-12-12 15:58:26 -08003582 do { visit(o, release_ref2, NULL); } while ((o = o->next) != obj);
3583
Josh Habermane8ed0212015-06-08 17:56:03 -07003584 /* Mark "group" fields as NULL so we know to free the objects later in
3585 * this loop, but also don't try to delete the group twice. */
Chris Fallin91473dc2014-12-12 15:58:26 -08003586 o = obj;
3587 do { o->group = NULL; } while ((o = o->next) != obj);
3588 }
3589 freeobj(obj);
3590 }
3591 }
3592
3593err4:
3594 if (!ret) {
Josh Habermane8ed0212015-06-08 17:56:03 -07003595 upb_inttable_begin(&iter, &t.groups);
3596 for(; !upb_inttable_done(&iter); upb_inttable_next(&iter))
3597 free(upb_value_getptr(upb_inttable_iter_value(&iter)));
Chris Fallin91473dc2014-12-12 15:58:26 -08003598 }
3599 upb_inttable_uninit(&t.groups);
3600err3:
3601 upb_inttable_uninit(&t.stack);
3602err2:
3603 upb_inttable_uninit(&t.objattr);
3604err1:
3605 return ret;
3606}
3607
3608
3609/* Misc internal functions ***************************************************/
3610
3611static bool merged(const upb_refcounted *r, const upb_refcounted *r2) {
3612 return r->group == r2->group;
3613}
3614
3615static void merge(upb_refcounted *r, upb_refcounted *from) {
Josh Habermane8ed0212015-06-08 17:56:03 -07003616 upb_refcounted *base;
3617 upb_refcounted *tmp;
3618
Chris Fallin91473dc2014-12-12 15:58:26 -08003619 if (merged(r, from)) return;
3620 *r->group += *from->group;
3621 free(from->group);
Josh Habermane8ed0212015-06-08 17:56:03 -07003622 base = from;
Chris Fallin91473dc2014-12-12 15:58:26 -08003623
Josh Habermane8ed0212015-06-08 17:56:03 -07003624 /* Set all refcount pointers in the "from" chain to the merged refcount.
3625 *
3626 * TODO(haberman): this linear algorithm can result in an overall O(n^2) bound
3627 * if the user continuously extends a group by one object. Prevent this by
3628 * using one of the techniques in this paper:
3629 * ftp://www.ncedc.org/outgoing/geomorph/dino/orals/p245-tarjan.pdf */
Chris Fallin91473dc2014-12-12 15:58:26 -08003630 do { from->group = r->group; } while ((from = from->next) != base);
3631
Josh Habermane8ed0212015-06-08 17:56:03 -07003632 /* Merge the two circularly linked lists by swapping their next pointers. */
3633 tmp = r->next;
Chris Fallin91473dc2014-12-12 15:58:26 -08003634 r->next = base->next;
3635 base->next = tmp;
3636}
3637
3638static void unref(const upb_refcounted *r);
3639
3640static void release_ref2(const upb_refcounted *obj,
3641 const upb_refcounted *subobj,
3642 void *closure) {
3643 UPB_UNUSED(closure);
3644 untrack(subobj, obj, true);
3645 if (!merged(obj, subobj)) {
3646 assert(subobj->is_frozen);
3647 unref(subobj);
3648 }
3649}
3650
3651static void unref(const upb_refcounted *r) {
3652 if (unrefgroup(r->group)) {
Josh Habermane8ed0212015-06-08 17:56:03 -07003653 const upb_refcounted *o;
3654
Chris Fallin91473dc2014-12-12 15:58:26 -08003655 free(r->group);
3656
Josh Habermane8ed0212015-06-08 17:56:03 -07003657 /* In two passes, since release_ref2 needs a guarantee that any subobjs
3658 * are alive. */
3659 o = r;
Chris Fallin91473dc2014-12-12 15:58:26 -08003660 do { visit(o, release_ref2, NULL); } while((o = o->next) != r);
3661
3662 o = r;
3663 do {
3664 const upb_refcounted *next = o->next;
3665 assert(o->is_frozen || o->individual_count == 0);
3666 freeobj((upb_refcounted*)o);
3667 o = next;
3668 } while(o != r);
3669 }
3670}
3671
3672static void freeobj(upb_refcounted *o) {
3673 trackfree(o);
3674 o->vtbl->free((upb_refcounted*)o);
3675}
3676
3677
3678/* Public interface ***********************************************************/
3679
3680bool upb_refcounted_init(upb_refcounted *r,
3681 const struct upb_refcounted_vtbl *vtbl,
3682 const void *owner) {
Josh Habermane8ed0212015-06-08 17:56:03 -07003683#ifndef NDEBUG
3684 /* Endianness check. This is unrelated to upb_refcounted, it's just a
3685 * convenient place to put the check that we can be assured will run for
3686 * basically every program using upb. */
3687 const int x = 1;
3688#ifdef UPB_BIG_ENDIAN
3689 assert(*(char*)&x != 1);
3690#else
3691 assert(*(char*)&x == 1);
3692#endif
3693#endif
3694
Chris Fallin91473dc2014-12-12 15:58:26 -08003695 r->next = r;
3696 r->vtbl = vtbl;
3697 r->individual_count = 0;
3698 r->is_frozen = false;
3699 r->group = malloc(sizeof(*r->group));
3700 if (!r->group) return false;
3701 *r->group = 0;
3702 if (!trackinit(r)) {
3703 free(r->group);
3704 return false;
3705 }
3706 upb_refcounted_ref(r, owner);
3707 return true;
3708}
3709
3710bool upb_refcounted_isfrozen(const upb_refcounted *r) {
3711 return r->is_frozen;
3712}
3713
3714void upb_refcounted_ref(const upb_refcounted *r, const void *owner) {
3715 track(r, owner, false);
3716 if (!r->is_frozen)
3717 ((upb_refcounted*)r)->individual_count++;
3718 refgroup(r->group);
3719}
3720
3721void upb_refcounted_unref(const upb_refcounted *r, const void *owner) {
3722 untrack(r, owner, false);
3723 if (!r->is_frozen)
3724 ((upb_refcounted*)r)->individual_count--;
3725 unref(r);
3726}
3727
3728void upb_refcounted_ref2(const upb_refcounted *r, upb_refcounted *from) {
Josh Habermane8ed0212015-06-08 17:56:03 -07003729 assert(!from->is_frozen); /* Non-const pointer implies this. */
Chris Fallin91473dc2014-12-12 15:58:26 -08003730 track(r, from, true);
3731 if (r->is_frozen) {
3732 refgroup(r->group);
3733 } else {
3734 merge((upb_refcounted*)r, from);
3735 }
3736}
3737
3738void upb_refcounted_unref2(const upb_refcounted *r, upb_refcounted *from) {
Josh Habermane8ed0212015-06-08 17:56:03 -07003739 assert(!from->is_frozen); /* Non-const pointer implies this. */
Chris Fallin91473dc2014-12-12 15:58:26 -08003740 untrack(r, from, true);
3741 if (r->is_frozen) {
3742 unref(r);
3743 } else {
3744 assert(merged(r, from));
3745 }
3746}
3747
3748void upb_refcounted_donateref(
3749 const upb_refcounted *r, const void *from, const void *to) {
3750 assert(from != to);
3751 if (to != NULL)
3752 upb_refcounted_ref(r, to);
3753 if (from != NULL)
3754 upb_refcounted_unref(r, from);
3755}
3756
3757void upb_refcounted_checkref(const upb_refcounted *r, const void *owner) {
3758 checkref(r, owner, false);
3759}
3760
3761bool upb_refcounted_freeze(upb_refcounted *const*roots, int n, upb_status *s,
3762 int maxdepth) {
Josh Habermane8ed0212015-06-08 17:56:03 -07003763 int i;
Josh Haberman94e54b32016-04-14 12:06:09 -07003764 bool ret;
Josh Habermane8ed0212015-06-08 17:56:03 -07003765 for (i = 0; i < n; i++) {
Chris Fallin91473dc2014-12-12 15:58:26 -08003766 assert(!roots[i]->is_frozen);
3767 }
Josh Haberman94e54b32016-04-14 12:06:09 -07003768 ret = freeze(roots, n, s, maxdepth);
3769 assert(!s || ret == upb_ok(s));
3770 return ret;
Chris Fallin91473dc2014-12-12 15:58:26 -08003771}
Chris Fallin91473dc2014-12-12 15:58:26 -08003772
3773
3774#include <stdlib.h>
3775
Josh Habermane8ed0212015-06-08 17:56:03 -07003776/* Fallback implementation if the shim is not specialized by the JIT. */
Chris Fallin91473dc2014-12-12 15:58:26 -08003777#define SHIM_WRITER(type, ctype) \
3778 bool upb_shim_set ## type (void *c, const void *hd, ctype val) { \
3779 uint8_t *m = c; \
3780 const upb_shim_data *d = hd; \
3781 if (d->hasbit > 0) \
3782 *(uint8_t*)&m[d->hasbit / 8] |= 1 << (d->hasbit % 8); \
3783 *(ctype*)&m[d->offset] = val; \
3784 return true; \
3785 } \
3786
3787SHIM_WRITER(double, double)
3788SHIM_WRITER(float, float)
3789SHIM_WRITER(int32, int32_t)
3790SHIM_WRITER(int64, int64_t)
3791SHIM_WRITER(uint32, uint32_t)
3792SHIM_WRITER(uint64, uint64_t)
3793SHIM_WRITER(bool, bool)
3794#undef SHIM_WRITER
3795
3796bool upb_shim_set(upb_handlers *h, const upb_fielddef *f, size_t offset,
3797 int32_t hasbit) {
Josh Habermane8ed0212015-06-08 17:56:03 -07003798 upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
3799 bool ok;
3800
Chris Fallin91473dc2014-12-12 15:58:26 -08003801 upb_shim_data *d = malloc(sizeof(*d));
3802 if (!d) return false;
3803 d->offset = offset;
3804 d->hasbit = hasbit;
3805
Chris Fallin91473dc2014-12-12 15:58:26 -08003806 upb_handlerattr_sethandlerdata(&attr, d);
3807 upb_handlerattr_setalwaysok(&attr, true);
3808 upb_handlers_addcleanup(h, d, free);
3809
3810#define TYPE(u, l) \
3811 case UPB_TYPE_##u: \
3812 ok = upb_handlers_set##l(h, f, upb_shim_set##l, &attr); break;
3813
Josh Habermane8ed0212015-06-08 17:56:03 -07003814 ok = false;
Chris Fallin91473dc2014-12-12 15:58:26 -08003815
3816 switch (upb_fielddef_type(f)) {
3817 TYPE(INT64, int64);
3818 TYPE(INT32, int32);
3819 TYPE(ENUM, int32);
3820 TYPE(UINT64, uint64);
3821 TYPE(UINT32, uint32);
3822 TYPE(DOUBLE, double);
3823 TYPE(FLOAT, float);
3824 TYPE(BOOL, bool);
3825 default: assert(false); break;
3826 }
3827#undef TYPE
3828
3829 upb_handlerattr_uninit(&attr);
3830 return ok;
3831}
3832
3833const upb_shim_data *upb_shim_getdata(const upb_handlers *h, upb_selector_t s,
3834 upb_fieldtype_t *type) {
3835 upb_func *f = upb_handlers_gethandler(h, s);
3836
3837 if ((upb_int64_handlerfunc*)f == upb_shim_setint64) {
3838 *type = UPB_TYPE_INT64;
3839 } else if ((upb_int32_handlerfunc*)f == upb_shim_setint32) {
3840 *type = UPB_TYPE_INT32;
3841 } else if ((upb_uint64_handlerfunc*)f == upb_shim_setuint64) {
3842 *type = UPB_TYPE_UINT64;
3843 } else if ((upb_uint32_handlerfunc*)f == upb_shim_setuint32) {
3844 *type = UPB_TYPE_UINT32;
3845 } else if ((upb_double_handlerfunc*)f == upb_shim_setdouble) {
3846 *type = UPB_TYPE_DOUBLE;
3847 } else if ((upb_float_handlerfunc*)f == upb_shim_setfloat) {
3848 *type = UPB_TYPE_FLOAT;
3849 } else if ((upb_bool_handlerfunc*)f == upb_shim_setbool) {
3850 *type = UPB_TYPE_BOOL;
3851 } else {
3852 return NULL;
3853 }
3854
3855 return (const upb_shim_data*)upb_handlers_gethandlerdata(h, s);
3856}
Chris Fallin91473dc2014-12-12 15:58:26 -08003857
3858
3859#include <stdlib.h>
3860#include <string.h>
3861
Chris Fallin91473dc2014-12-12 15:58:26 -08003862static void upb_symtab_free(upb_refcounted *r) {
3863 upb_symtab *s = (upb_symtab*)r;
3864 upb_strtable_iter i;
3865 upb_strtable_begin(&i, &s->symtab);
3866 for (; !upb_strtable_done(&i); upb_strtable_next(&i)) {
3867 const upb_def *def = upb_value_getptr(upb_strtable_iter_value(&i));
3868 upb_def_unref(def, s);
3869 }
3870 upb_strtable_uninit(&s->symtab);
3871 free(s);
3872}
3873
3874
3875upb_symtab *upb_symtab_new(const void *owner) {
3876 static const struct upb_refcounted_vtbl vtbl = {NULL, &upb_symtab_free};
3877 upb_symtab *s = malloc(sizeof(*s));
Josh Habermane8ed0212015-06-08 17:56:03 -07003878 upb_refcounted_init(upb_symtab_upcast_mutable(s), &vtbl, owner);
Chris Fallin91473dc2014-12-12 15:58:26 -08003879 upb_strtable_init(&s->symtab, UPB_CTYPE_PTR);
3880 return s;
3881}
3882
3883void upb_symtab_freeze(upb_symtab *s) {
Josh Habermane8ed0212015-06-08 17:56:03 -07003884 upb_refcounted *r;
3885 bool ok;
3886
Chris Fallin91473dc2014-12-12 15:58:26 -08003887 assert(!upb_symtab_isfrozen(s));
Josh Habermane8ed0212015-06-08 17:56:03 -07003888 r = upb_symtab_upcast_mutable(s);
3889 /* The symtab does not take ref2's (see refcounted.h) on the defs, because
3890 * defs cannot refer back to the table and therefore cannot create cycles. So
3891 * 0 will suffice for maxdepth here. */
3892 ok = upb_refcounted_freeze(&r, 1, NULL, 0);
Chris Fallin91473dc2014-12-12 15:58:26 -08003893 UPB_ASSERT_VAR(ok, ok);
3894}
3895
3896const upb_def *upb_symtab_lookup(const upb_symtab *s, const char *sym) {
3897 upb_value v;
3898 upb_def *ret = upb_strtable_lookup(&s->symtab, sym, &v) ?
3899 upb_value_getptr(v) : NULL;
3900 return ret;
3901}
3902
3903const upb_msgdef *upb_symtab_lookupmsg(const upb_symtab *s, const char *sym) {
3904 upb_value v;
3905 upb_def *def = upb_strtable_lookup(&s->symtab, sym, &v) ?
3906 upb_value_getptr(v) : NULL;
3907 return def ? upb_dyncast_msgdef(def) : NULL;
3908}
3909
3910const upb_enumdef *upb_symtab_lookupenum(const upb_symtab *s, const char *sym) {
3911 upb_value v;
3912 upb_def *def = upb_strtable_lookup(&s->symtab, sym, &v) ?
3913 upb_value_getptr(v) : NULL;
3914 return def ? upb_dyncast_enumdef(def) : NULL;
3915}
3916
Josh Habermane8ed0212015-06-08 17:56:03 -07003917/* Given a symbol and the base symbol inside which it is defined, find the
3918 * symbol's definition in t. */
Chris Fallin91473dc2014-12-12 15:58:26 -08003919static upb_def *upb_resolvename(const upb_strtable *t,
3920 const char *base, const char *sym) {
3921 if(strlen(sym) == 0) return NULL;
3922 if(sym[0] == '.') {
Josh Habermane8ed0212015-06-08 17:56:03 -07003923 /* Symbols starting with '.' are absolute, so we do a single lookup.
3924 * Slice to omit the leading '.' */
Chris Fallin91473dc2014-12-12 15:58:26 -08003925 upb_value v;
3926 return upb_strtable_lookup(t, sym + 1, &v) ? upb_value_getptr(v) : NULL;
3927 } else {
Josh Habermane8ed0212015-06-08 17:56:03 -07003928 /* Remove components from base until we find an entry or run out.
3929 * TODO: This branch is totally broken, but currently not used. */
Chris Fallin91473dc2014-12-12 15:58:26 -08003930 (void)base;
3931 assert(false);
3932 return NULL;
3933 }
3934}
3935
3936const upb_def *upb_symtab_resolve(const upb_symtab *s, const char *base,
3937 const char *sym) {
3938 upb_def *ret = upb_resolvename(&s->symtab, base, sym);
3939 return ret;
3940}
3941
Josh Habermanfb8ed702015-06-22 17:23:55 -07003942/* Starts a depth-first traversal at "def", recursing into any subdefs
3943 * (ie. submessage types). Adds duplicates of existing defs to addtab
3944 * wherever necessary, so that the resulting symtab will be consistent once
3945 * addtab is added.
Josh Habermane8ed0212015-06-08 17:56:03 -07003946 *
Josh Habermanfb8ed702015-06-22 17:23:55 -07003947 * More specifically, if any def D is found in the DFS that:
3948 *
3949 * 1. can reach a def that is being replaced by something in addtab, AND
3950 *
3951 * 2. is not itself being replaced already (ie. this name doesn't already
3952 * exist in addtab)
3953 *
3954 * ...then a duplicate (new copy) of D will be added to addtab.
3955 *
3956 * Returns true if this happened for any def reachable from "def."
3957 *
3958 * It is slightly tricky to do this correctly in the presence of cycles. If we
3959 * detect that our DFS has hit a cycle, we might not yet know if any SCCs on
3960 * our stack can reach a def in addtab or not. Once we figure this out, that
3961 * answer needs to apply to *all* defs in these SCCs, even if we visited them
3962 * already. So a straight up one-pass cycle-detecting DFS won't work.
3963 *
3964 * To work around this problem, we traverse each SCC (which we already
3965 * computed, since these defs are frozen) as a single node. We first compute
3966 * whether the SCC as a whole can reach any def in addtab, then we dup (or not)
3967 * the entire SCC. This requires breaking the encapsulation of upb_refcounted,
3968 * since that is where we get the data about what SCC we are in. */
Chris Fallin91473dc2014-12-12 15:58:26 -08003969static bool upb_resolve_dfs(const upb_def *def, upb_strtable *addtab,
3970 const void *new_owner, upb_inttable *seen,
3971 upb_status *s) {
Chris Fallin91473dc2014-12-12 15:58:26 -08003972 upb_value v;
Josh Habermane8ed0212015-06-08 17:56:03 -07003973 bool need_dup;
3974 const upb_def *base;
Josh Habermanfb8ed702015-06-22 17:23:55 -07003975 const void* memoize_key;
Josh Habermane8ed0212015-06-08 17:56:03 -07003976
Josh Habermanfb8ed702015-06-22 17:23:55 -07003977 /* Memoize results of this function for efficiency (since we're traversing a
3978 * DAG this is not needed to limit the depth of the search).
3979 *
3980 * We memoize by SCC instead of by individual def. */
3981 memoize_key = def->base.group;
3982
3983 if (upb_inttable_lookupptr(seen, memoize_key, &v))
Chris Fallin91473dc2014-12-12 15:58:26 -08003984 return upb_value_getbool(v);
3985
Josh Habermane8ed0212015-06-08 17:56:03 -07003986 /* Visit submessages for all messages in the SCC. */
3987 need_dup = false;
3988 base = def;
Chris Fallin91473dc2014-12-12 15:58:26 -08003989 do {
Josh Habermane8ed0212015-06-08 17:56:03 -07003990 upb_value v;
3991 const upb_msgdef *m;
3992
Chris Fallin91473dc2014-12-12 15:58:26 -08003993 assert(upb_def_isfrozen(def));
3994 if (def->type == UPB_DEF_FIELD) continue;
Chris Fallin91473dc2014-12-12 15:58:26 -08003995 if (upb_strtable_lookup(addtab, upb_def_fullname(def), &v)) {
3996 need_dup = true;
3997 }
3998
Josh Habermanfb8ed702015-06-22 17:23:55 -07003999 /* For messages, continue the recursion by visiting all subdefs, but only
4000 * ones in different SCCs. */
Josh Habermane8ed0212015-06-08 17:56:03 -07004001 m = upb_dyncast_msgdef(def);
Chris Fallin91473dc2014-12-12 15:58:26 -08004002 if (m) {
Chris Fallinfcd88892015-01-13 18:14:39 -08004003 upb_msg_field_iter i;
4004 for(upb_msg_field_begin(&i, m);
4005 !upb_msg_field_done(&i);
4006 upb_msg_field_next(&i)) {
Chris Fallin91473dc2014-12-12 15:58:26 -08004007 upb_fielddef *f = upb_msg_iter_field(&i);
Josh Habermanfb8ed702015-06-22 17:23:55 -07004008 const upb_def *subdef;
4009
Chris Fallin91473dc2014-12-12 15:58:26 -08004010 if (!upb_fielddef_hassubdef(f)) continue;
Josh Habermanfb8ed702015-06-22 17:23:55 -07004011 subdef = upb_fielddef_subdef(f);
4012
4013 /* Skip subdefs in this SCC. */
4014 if (def->base.group == subdef->base.group) continue;
4015
Josh Habermane8ed0212015-06-08 17:56:03 -07004016 /* |= to avoid short-circuit; we need its side-effects. */
Josh Habermanfb8ed702015-06-22 17:23:55 -07004017 need_dup |= upb_resolve_dfs(subdef, addtab, new_owner, seen, s);
Chris Fallin91473dc2014-12-12 15:58:26 -08004018 if (!upb_ok(s)) return false;
4019 }
4020 }
4021 } while ((def = (upb_def*)def->base.next) != base);
4022
4023 if (need_dup) {
Josh Habermanfb8ed702015-06-22 17:23:55 -07004024 /* Dup all defs in this SCC that don't already have entries in addtab. */
Chris Fallin91473dc2014-12-12 15:58:26 -08004025 def = base;
4026 do {
Josh Habermane8ed0212015-06-08 17:56:03 -07004027 const char *name;
4028
Chris Fallin91473dc2014-12-12 15:58:26 -08004029 if (def->type == UPB_DEF_FIELD) continue;
Josh Habermane8ed0212015-06-08 17:56:03 -07004030 name = upb_def_fullname(def);
Chris Fallin91473dc2014-12-12 15:58:26 -08004031 if (!upb_strtable_lookup(addtab, name, NULL)) {
4032 upb_def *newdef = upb_def_dup(def, new_owner);
4033 if (!newdef) goto oom;
4034 newdef->came_from_user = false;
4035 if (!upb_strtable_insert(addtab, name, upb_value_ptr(newdef)))
4036 goto oom;
4037 }
4038 } while ((def = (upb_def*)def->base.next) != base);
4039 }
4040
Josh Habermanfb8ed702015-06-22 17:23:55 -07004041 upb_inttable_insertptr(seen, memoize_key, upb_value_bool(need_dup));
Chris Fallin91473dc2014-12-12 15:58:26 -08004042 return need_dup;
4043
4044oom:
4045 upb_status_seterrmsg(s, "out of memory");
4046 return false;
4047}
4048
Josh Habermane8ed0212015-06-08 17:56:03 -07004049/* TODO(haberman): we need a lot more testing of error conditions.
4050 * The came_from_user stuff in particular is not tested. */
Josh Haberman94e54b32016-04-14 12:06:09 -07004051static bool symtab_add(upb_symtab *s, upb_def *const*defs, size_t n,
4052 void *ref_donor, upb_refcounted *freeze_also,
4053 upb_status *status) {
4054 size_t i;
4055 size_t add_n;
4056 size_t freeze_n;
Josh Habermane8ed0212015-06-08 17:56:03 -07004057 upb_strtable_iter iter;
Josh Haberman94e54b32016-04-14 12:06:09 -07004058 upb_refcounted **add_objs = NULL;
Chris Fallin91473dc2014-12-12 15:58:26 -08004059 upb_def **add_defs = NULL;
Josh Haberman94e54b32016-04-14 12:06:09 -07004060 size_t add_objs_size;
Chris Fallin91473dc2014-12-12 15:58:26 -08004061 upb_strtable addtab;
Josh Habermane8ed0212015-06-08 17:56:03 -07004062 upb_inttable seen;
4063
4064 assert(!upb_symtab_isfrozen(s));
Chris Fallin91473dc2014-12-12 15:58:26 -08004065 if (!upb_strtable_init(&addtab, UPB_CTYPE_PTR)) {
4066 upb_status_seterrmsg(status, "out of memory");
4067 return false;
4068 }
4069
Josh Habermane8ed0212015-06-08 17:56:03 -07004070 /* Add new defs to our "add" set. */
4071 for (i = 0; i < n; i++) {
Chris Fallin91473dc2014-12-12 15:58:26 -08004072 upb_def *def = defs[i];
Josh Habermane8ed0212015-06-08 17:56:03 -07004073 const char *fullname;
4074 upb_fielddef *f;
4075
Chris Fallin91473dc2014-12-12 15:58:26 -08004076 if (upb_def_isfrozen(def)) {
4077 upb_status_seterrmsg(status, "added defs must be mutable");
4078 goto err;
4079 }
4080 assert(!upb_def_isfrozen(def));
Josh Habermane8ed0212015-06-08 17:56:03 -07004081 fullname = upb_def_fullname(def);
Chris Fallin91473dc2014-12-12 15:58:26 -08004082 if (!fullname) {
4083 upb_status_seterrmsg(
4084 status, "Anonymous defs cannot be added to a symtab");
4085 goto err;
4086 }
4087
Josh Habermane8ed0212015-06-08 17:56:03 -07004088 f = upb_dyncast_fielddef_mutable(def);
Chris Fallin91473dc2014-12-12 15:58:26 -08004089
4090 if (f) {
4091 if (!upb_fielddef_containingtypename(f)) {
4092 upb_status_seterrmsg(status,
4093 "Standalone fielddefs must have a containing type "
4094 "(extendee) name set");
4095 goto err;
4096 }
4097 } else {
4098 if (upb_strtable_lookup(&addtab, fullname, NULL)) {
4099 upb_status_seterrf(status, "Conflicting defs named '%s'", fullname);
4100 goto err;
4101 }
Josh Habermane8ed0212015-06-08 17:56:03 -07004102 /* We need this to back out properly, because if there is a failure we
4103 * need to donate the ref back to the caller. */
Chris Fallin91473dc2014-12-12 15:58:26 -08004104 def->came_from_user = true;
4105 upb_def_donateref(def, ref_donor, s);
4106 if (!upb_strtable_insert(&addtab, fullname, upb_value_ptr(def)))
4107 goto oom_err;
4108 }
4109 }
4110
Josh Habermane8ed0212015-06-08 17:56:03 -07004111 /* Add standalone fielddefs (ie. extensions) to the appropriate messages.
4112 * If the appropriate message only exists in the existing symtab, duplicate
4113 * it so we have a mutable copy we can add the fields to. */
4114 for (i = 0; i < n; i++) {
Chris Fallin91473dc2014-12-12 15:58:26 -08004115 upb_def *def = defs[i];
4116 upb_fielddef *f = upb_dyncast_fielddef_mutable(def);
Josh Habermane8ed0212015-06-08 17:56:03 -07004117 const char *msgname;
4118 upb_value v;
4119 upb_msgdef *m;
4120
Chris Fallin91473dc2014-12-12 15:58:26 -08004121 if (!f) continue;
Josh Habermane8ed0212015-06-08 17:56:03 -07004122 msgname = upb_fielddef_containingtypename(f);
4123 /* We validated this earlier in this function. */
Chris Fallin91473dc2014-12-12 15:58:26 -08004124 assert(msgname);
4125
Josh Habermane8ed0212015-06-08 17:56:03 -07004126 /* If the extendee name is absolutely qualified, move past the initial ".".
4127 * TODO(haberman): it is not obvious what it would mean if this was not
4128 * absolutely qualified. */
Chris Fallin91473dc2014-12-12 15:58:26 -08004129 if (msgname[0] == '.') {
4130 msgname++;
4131 }
4132
Chris Fallin91473dc2014-12-12 15:58:26 -08004133 if (upb_strtable_lookup(&addtab, msgname, &v)) {
Josh Habermane8ed0212015-06-08 17:56:03 -07004134 /* Extendee is in the set of defs the user asked us to add. */
Chris Fallin91473dc2014-12-12 15:58:26 -08004135 m = upb_value_getptr(v);
4136 } else {
Josh Habermane8ed0212015-06-08 17:56:03 -07004137 /* Need to find and dup the extendee from the existing symtab. */
Chris Fallin91473dc2014-12-12 15:58:26 -08004138 const upb_msgdef *frozen_m = upb_symtab_lookupmsg(s, msgname);
4139 if (!frozen_m) {
4140 upb_status_seterrf(status,
4141 "Tried to extend message %s that does not exist "
4142 "in this SymbolTable.",
4143 msgname);
4144 goto err;
4145 }
4146 m = upb_msgdef_dup(frozen_m, s);
4147 if (!m) goto oom_err;
4148 if (!upb_strtable_insert(&addtab, msgname, upb_value_ptr(m))) {
4149 upb_msgdef_unref(m, s);
4150 goto oom_err;
4151 }
4152 }
4153
4154 if (!upb_msgdef_addfield(m, f, ref_donor, status)) {
4155 goto err;
4156 }
4157 }
4158
Josh Habermane8ed0212015-06-08 17:56:03 -07004159 /* Add dups of any existing def that can reach a def with the same name as
4160 * anything in our "add" set. */
Chris Fallin91473dc2014-12-12 15:58:26 -08004161 if (!upb_inttable_init(&seen, UPB_CTYPE_BOOL)) goto oom_err;
Josh Habermane8ed0212015-06-08 17:56:03 -07004162 upb_strtable_begin(&iter, &s->symtab);
4163 for (; !upb_strtable_done(&iter); upb_strtable_next(&iter)) {
4164 upb_def *def = upb_value_getptr(upb_strtable_iter_value(&iter));
Chris Fallin91473dc2014-12-12 15:58:26 -08004165 upb_resolve_dfs(def, &addtab, s, &seen, status);
4166 if (!upb_ok(status)) goto err;
4167 }
4168 upb_inttable_uninit(&seen);
4169
Josh Habermane8ed0212015-06-08 17:56:03 -07004170 /* Now using the table, resolve symbolic references for subdefs. */
4171 upb_strtable_begin(&iter, &addtab);
4172 for (; !upb_strtable_done(&iter); upb_strtable_next(&iter)) {
4173 const char *base;
4174 upb_def *def = upb_value_getptr(upb_strtable_iter_value(&iter));
Chris Fallin91473dc2014-12-12 15:58:26 -08004175 upb_msgdef *m = upb_dyncast_msgdef_mutable(def);
Chris Fallinfcd88892015-01-13 18:14:39 -08004176 upb_msg_field_iter j;
Josh Habermane8ed0212015-06-08 17:56:03 -07004177
4178 if (!m) continue;
4179 /* Type names are resolved relative to the message in which they appear. */
4180 base = upb_msgdef_fullname(m);
4181
Chris Fallinfcd88892015-01-13 18:14:39 -08004182 for(upb_msg_field_begin(&j, m);
4183 !upb_msg_field_done(&j);
4184 upb_msg_field_next(&j)) {
Chris Fallin91473dc2014-12-12 15:58:26 -08004185 upb_fielddef *f = upb_msg_iter_field(&j);
4186 const char *name = upb_fielddef_subdefname(f);
4187 if (name && !upb_fielddef_subdef(f)) {
Josh Habermane8ed0212015-06-08 17:56:03 -07004188 /* Try the lookup in the current set of to-be-added defs first. If not
4189 * there, try existing defs. */
Chris Fallin91473dc2014-12-12 15:58:26 -08004190 upb_def *subdef = upb_resolvename(&addtab, base, name);
4191 if (subdef == NULL) {
4192 subdef = upb_resolvename(&s->symtab, base, name);
4193 }
4194 if (subdef == NULL) {
4195 upb_status_seterrf(
4196 status, "couldn't resolve name '%s' in message '%s'", name, base);
4197 goto err;
4198 } else if (!upb_fielddef_setsubdef(f, subdef, status)) {
4199 goto err;
4200 }
4201 }
4202 }
4203 }
4204
Josh Haberman94e54b32016-04-14 12:06:09 -07004205 /* We need an array of the defs in addtab, for passing to
4206 * upb_refcounted_freeze(). */
4207 add_objs_size = upb_strtable_count(&addtab);
4208 if (freeze_also) {
4209 add_objs_size++;
Chris Fallin91473dc2014-12-12 15:58:26 -08004210 }
4211
Josh Haberman94e54b32016-04-14 12:06:09 -07004212 add_defs = malloc(sizeof(void*) * add_objs_size);
4213 if (add_defs == NULL) goto oom_err;
4214 upb_strtable_begin(&iter, &addtab);
4215 for (add_n = 0; !upb_strtable_done(&iter); upb_strtable_next(&iter)) {
4216 add_defs[add_n++] = upb_value_getptr(upb_strtable_iter_value(&iter));
4217 }
4218
4219 /* Validate defs. */
4220 if (!_upb_def_validate(add_defs, add_n, status)) {
4221 goto err;
4222 }
4223
4224 /* Cheat a little and give the array a new type.
4225 * This is probably undefined behavior, but this code will be deleted soon. */
4226 add_objs = (upb_refcounted**)add_defs;
4227
4228 freeze_n = add_n;
4229 if (freeze_also) {
4230 add_objs[freeze_n++] = freeze_also;
4231 }
4232
4233 if (!upb_refcounted_freeze(add_objs, freeze_n, status,
4234 UPB_MAX_MESSAGE_DEPTH * 2)) {
4235 goto err;
4236 }
Chris Fallin91473dc2014-12-12 15:58:26 -08004237
Josh Habermane8ed0212015-06-08 17:56:03 -07004238 /* This must be delayed until all errors have been detected, since error
4239 * recovery code uses this table to cleanup defs. */
Chris Fallin91473dc2014-12-12 15:58:26 -08004240 upb_strtable_uninit(&addtab);
4241
Josh Habermane8ed0212015-06-08 17:56:03 -07004242 /* TODO(haberman) we don't properly handle errors after this point (like
4243 * OOM in upb_strtable_insert() below). */
Josh Haberman94e54b32016-04-14 12:06:09 -07004244 for (i = 0; i < add_n; i++) {
4245 upb_def *def = (upb_def*)add_objs[i];
Chris Fallin91473dc2014-12-12 15:58:26 -08004246 const char *name = upb_def_fullname(def);
4247 upb_value v;
Josh Habermane8ed0212015-06-08 17:56:03 -07004248 bool success;
4249
Chris Fallin91473dc2014-12-12 15:58:26 -08004250 if (upb_strtable_remove(&s->symtab, name, &v)) {
4251 const upb_def *def = upb_value_getptr(v);
4252 upb_def_unref(def, s);
4253 }
Josh Habermane8ed0212015-06-08 17:56:03 -07004254 success = upb_strtable_insert(&s->symtab, name, upb_value_ptr(def));
Chris Fallin91473dc2014-12-12 15:58:26 -08004255 UPB_ASSERT_VAR(success, success == true);
4256 }
Josh Haberman94e54b32016-04-14 12:06:09 -07004257 free(add_objs);
Chris Fallin91473dc2014-12-12 15:58:26 -08004258 return true;
4259
4260oom_err:
4261 upb_status_seterrmsg(status, "out of memory");
4262err: {
Josh Habermane8ed0212015-06-08 17:56:03 -07004263 /* For defs the user passed in, we need to donate the refs back. For defs
4264 * we dup'd, we need to just unref them. */
4265 upb_strtable_begin(&iter, &addtab);
4266 for (; !upb_strtable_done(&iter); upb_strtable_next(&iter)) {
4267 upb_def *def = upb_value_getptr(upb_strtable_iter_value(&iter));
Chris Fallin91473dc2014-12-12 15:58:26 -08004268 bool came_from_user = def->came_from_user;
4269 def->came_from_user = false;
4270 if (came_from_user) {
4271 upb_def_donateref(def, s, ref_donor);
4272 } else {
4273 upb_def_unref(def, s);
4274 }
4275 }
4276 }
4277 upb_strtable_uninit(&addtab);
Josh Haberman94e54b32016-04-14 12:06:09 -07004278 free(add_objs);
Chris Fallin91473dc2014-12-12 15:58:26 -08004279 assert(!upb_ok(status));
4280 return false;
4281}
4282
Josh Haberman94e54b32016-04-14 12:06:09 -07004283bool upb_symtab_add(upb_symtab *s, upb_def *const*defs, size_t n,
4284 void *ref_donor, upb_status *status) {
4285 return symtab_add(s, defs, n, ref_donor, NULL, status);
4286}
4287
4288bool upb_symtab_addfile(upb_symtab *s, upb_filedef *file, upb_status *status) {
4289 size_t n;
4290 size_t i;
4291 upb_def **defs;
4292 bool ret;
4293
4294 n = upb_filedef_defcount(file);
4295 defs = malloc(sizeof(*defs) * n);
4296
4297 if (defs == NULL) {
4298 upb_status_seterrmsg(status, "Out of memory");
4299 return false;
4300 }
4301
4302 for (i = 0; i < n; i++) {
4303 defs[i] = upb_filedef_mutabledef(file, i);
4304 }
4305
4306 ret = symtab_add(s, defs, n, NULL, upb_filedef_upcast_mutable(file), status);
4307
4308 free(defs);
4309 return ret;
4310}
4311
Josh Habermane8ed0212015-06-08 17:56:03 -07004312/* Iteration. */
Chris Fallin91473dc2014-12-12 15:58:26 -08004313
4314static void advance_to_matching(upb_symtab_iter *iter) {
4315 if (iter->type == UPB_DEF_ANY)
4316 return;
4317
4318 while (!upb_strtable_done(&iter->iter) &&
4319 iter->type != upb_symtab_iter_def(iter)->type) {
4320 upb_strtable_next(&iter->iter);
4321 }
4322}
4323
4324void upb_symtab_begin(upb_symtab_iter *iter, const upb_symtab *s,
4325 upb_deftype_t type) {
4326 upb_strtable_begin(&iter->iter, &s->symtab);
4327 iter->type = type;
4328 advance_to_matching(iter);
4329}
4330
4331void upb_symtab_next(upb_symtab_iter *iter) {
4332 upb_strtable_next(&iter->iter);
4333 advance_to_matching(iter);
4334}
4335
4336bool upb_symtab_done(const upb_symtab_iter *iter) {
4337 return upb_strtable_done(&iter->iter);
4338}
4339
4340const upb_def *upb_symtab_iter_def(const upb_symtab_iter *iter) {
4341 return upb_value_getptr(upb_strtable_iter_value(&iter->iter));
4342}
4343/*
Josh Haberman181c7f22015-07-15 11:05:10 -07004344** upb_table Implementation
4345**
4346** Implementation is heavily inspired by Lua's ltable.c.
4347*/
Chris Fallin91473dc2014-12-12 15:58:26 -08004348
4349
4350#include <stdlib.h>
4351#include <string.h>
4352
Josh Habermane8ed0212015-06-08 17:56:03 -07004353#define UPB_MAXARRSIZE 16 /* 64k. */
Chris Fallin91473dc2014-12-12 15:58:26 -08004354
Josh Habermane8ed0212015-06-08 17:56:03 -07004355/* From Chromium. */
Chris Fallin91473dc2014-12-12 15:58:26 -08004356#define ARRAY_SIZE(x) \
4357 ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x])))))
4358
4359static const double MAX_LOAD = 0.85;
4360
Josh Habermane8ed0212015-06-08 17:56:03 -07004361/* The minimum utilization of the array part of a mixed hash/array table. This
4362 * is a speed/memory-usage tradeoff (though it's not straightforward because of
4363 * cache effects). The lower this is, the more memory we'll use. */
Chris Fallin91473dc2014-12-12 15:58:26 -08004364static const double MIN_DENSITY = 0.1;
4365
4366bool is_pow2(uint64_t v) { return v == 0 || (v & (v - 1)) == 0; }
4367
4368int log2ceil(uint64_t v) {
4369 int ret = 0;
4370 bool pow2 = is_pow2(v);
4371 while (v >>= 1) ret++;
Josh Habermane8ed0212015-06-08 17:56:03 -07004372 ret = pow2 ? ret : ret + 1; /* Ceiling. */
Chris Fallin91473dc2014-12-12 15:58:26 -08004373 return UPB_MIN(UPB_MAXARRSIZE, ret);
4374}
4375
4376char *upb_strdup(const char *s) {
Chris Fallinfd1a3ff2015-01-06 15:44:09 -08004377 return upb_strdup2(s, strlen(s));
4378}
4379
4380char *upb_strdup2(const char *s, size_t len) {
Josh Habermane8ed0212015-06-08 17:56:03 -07004381 size_t n;
4382 char *p;
4383
4384 /* Prevent overflow errors. */
Chris Fallina5075922015-02-02 15:07:34 -08004385 if (len == SIZE_MAX) return NULL;
Josh Habermane8ed0212015-06-08 17:56:03 -07004386 /* Always null-terminate, even if binary data; but don't rely on the input to
4387 * have a null-terminating byte since it may be a raw binary buffer. */
4388 n = len + 1;
4389 p = malloc(n);
Chris Fallina5075922015-02-02 15:07:34 -08004390 if (p) {
4391 memcpy(p, s, len);
4392 p[len] = 0;
4393 }
Chris Fallin91473dc2014-12-12 15:58:26 -08004394 return p;
4395}
4396
Josh Habermane8ed0212015-06-08 17:56:03 -07004397/* A type to represent the lookup key of either a strtable or an inttable. */
4398typedef union {
4399 uintptr_t num;
4400 struct {
4401 const char *str;
4402 size_t len;
4403 } str;
Chris Fallin91473dc2014-12-12 15:58:26 -08004404} lookupkey_t;
4405
Chris Fallin91473dc2014-12-12 15:58:26 -08004406static lookupkey_t strkey2(const char *str, size_t len) {
4407 lookupkey_t k;
Josh Habermane8ed0212015-06-08 17:56:03 -07004408 k.str.str = str;
4409 k.str.len = len;
Chris Fallin91473dc2014-12-12 15:58:26 -08004410 return k;
4411}
4412
4413static lookupkey_t intkey(uintptr_t key) {
4414 lookupkey_t k;
Josh Habermane8ed0212015-06-08 17:56:03 -07004415 k.num = key;
Chris Fallin91473dc2014-12-12 15:58:26 -08004416 return k;
4417}
4418
4419typedef uint32_t hashfunc_t(upb_tabkey key);
4420typedef bool eqlfunc_t(upb_tabkey k1, lookupkey_t k2);
4421
4422/* Base table (shared code) ***************************************************/
4423
Josh Habermane8ed0212015-06-08 17:56:03 -07004424/* For when we need to cast away const. */
Chris Fallin91473dc2014-12-12 15:58:26 -08004425static upb_tabent *mutable_entries(upb_table *t) {
4426 return (upb_tabent*)t->entries;
4427}
4428
4429static bool isfull(upb_table *t) {
Josh Habermanf654d492016-02-18 11:07:51 -08004430 if (upb_table_size(t) == 0) {
4431 return true;
4432 } else {
4433 return ((double)(t->count + 1) / upb_table_size(t)) > MAX_LOAD;
4434 }
Chris Fallin91473dc2014-12-12 15:58:26 -08004435}
4436
4437static bool init(upb_table *t, upb_ctype_t ctype, uint8_t size_lg2) {
Josh Habermane8ed0212015-06-08 17:56:03 -07004438 size_t bytes;
4439
Chris Fallin91473dc2014-12-12 15:58:26 -08004440 t->count = 0;
4441 t->ctype = ctype;
4442 t->size_lg2 = size_lg2;
4443 t->mask = upb_table_size(t) ? upb_table_size(t) - 1 : 0;
Josh Habermane8ed0212015-06-08 17:56:03 -07004444 bytes = upb_table_size(t) * sizeof(upb_tabent);
Chris Fallin91473dc2014-12-12 15:58:26 -08004445 if (bytes > 0) {
4446 t->entries = malloc(bytes);
4447 if (!t->entries) return false;
4448 memset(mutable_entries(t), 0, bytes);
4449 } else {
4450 t->entries = NULL;
4451 }
4452 return true;
4453}
4454
4455static void uninit(upb_table *t) { free(mutable_entries(t)); }
4456
4457static upb_tabent *emptyent(upb_table *t) {
4458 upb_tabent *e = mutable_entries(t) + upb_table_size(t);
4459 while (1) { if (upb_tabent_isempty(--e)) return e; assert(e > t->entries); }
4460}
4461
4462static upb_tabent *getentry_mutable(upb_table *t, uint32_t hash) {
4463 return (upb_tabent*)upb_getentry(t, hash);
4464}
4465
4466static const upb_tabent *findentry(const upb_table *t, lookupkey_t key,
4467 uint32_t hash, eqlfunc_t *eql) {
Josh Habermane8ed0212015-06-08 17:56:03 -07004468 const upb_tabent *e;
4469
Chris Fallin91473dc2014-12-12 15:58:26 -08004470 if (t->size_lg2 == 0) return NULL;
Josh Habermane8ed0212015-06-08 17:56:03 -07004471 e = upb_getentry(t, hash);
Chris Fallin91473dc2014-12-12 15:58:26 -08004472 if (upb_tabent_isempty(e)) return NULL;
4473 while (1) {
4474 if (eql(e->key, key)) return e;
4475 if ((e = e->next) == NULL) return NULL;
4476 }
4477}
4478
4479static upb_tabent *findentry_mutable(upb_table *t, lookupkey_t key,
4480 uint32_t hash, eqlfunc_t *eql) {
4481 return (upb_tabent*)findentry(t, key, hash, eql);
4482}
4483
4484static bool lookup(const upb_table *t, lookupkey_t key, upb_value *v,
4485 uint32_t hash, eqlfunc_t *eql) {
4486 const upb_tabent *e = findentry(t, key, hash, eql);
4487 if (e) {
4488 if (v) {
Josh Habermane8ed0212015-06-08 17:56:03 -07004489 _upb_value_setval(v, e->val.val, t->ctype);
Chris Fallin91473dc2014-12-12 15:58:26 -08004490 }
4491 return true;
4492 } else {
4493 return false;
4494 }
4495}
4496
Josh Habermane8ed0212015-06-08 17:56:03 -07004497/* The given key must not already exist in the table. */
4498static void insert(upb_table *t, lookupkey_t key, upb_tabkey tabkey,
4499 upb_value val, uint32_t hash,
4500 hashfunc_t *hashfunc, eqlfunc_t *eql) {
4501 upb_tabent *mainpos_e;
4502 upb_tabent *our_e;
4503
Chris Fallin91473dc2014-12-12 15:58:26 -08004504 UPB_UNUSED(eql);
Josh Habermane8ed0212015-06-08 17:56:03 -07004505 UPB_UNUSED(key);
Chris Fallin91473dc2014-12-12 15:58:26 -08004506 assert(findentry(t, key, hash, eql) == NULL);
4507 assert(val.ctype == t->ctype);
Josh Habermane8ed0212015-06-08 17:56:03 -07004508
Chris Fallin91473dc2014-12-12 15:58:26 -08004509 t->count++;
Josh Habermane8ed0212015-06-08 17:56:03 -07004510 mainpos_e = getentry_mutable(t, hash);
4511 our_e = mainpos_e;
4512
Chris Fallin91473dc2014-12-12 15:58:26 -08004513 if (upb_tabent_isempty(mainpos_e)) {
Josh Habermane8ed0212015-06-08 17:56:03 -07004514 /* Our main position is empty; use it. */
Chris Fallin91473dc2014-12-12 15:58:26 -08004515 our_e->next = NULL;
4516 } else {
Josh Habermane8ed0212015-06-08 17:56:03 -07004517 /* Collision. */
Chris Fallin91473dc2014-12-12 15:58:26 -08004518 upb_tabent *new_e = emptyent(t);
Josh Habermane8ed0212015-06-08 17:56:03 -07004519 /* Head of collider's chain. */
Chris Fallin91473dc2014-12-12 15:58:26 -08004520 upb_tabent *chain = getentry_mutable(t, hashfunc(mainpos_e->key));
4521 if (chain == mainpos_e) {
Josh Habermane8ed0212015-06-08 17:56:03 -07004522 /* Existing ent is in its main posisiton (it has the same hash as us, and
4523 * is the head of our chain). Insert to new ent and append to this chain. */
Chris Fallin91473dc2014-12-12 15:58:26 -08004524 new_e->next = mainpos_e->next;
4525 mainpos_e->next = new_e;
4526 our_e = new_e;
4527 } else {
Josh Habermane8ed0212015-06-08 17:56:03 -07004528 /* Existing ent is not in its main position (it is a node in some other
4529 * chain). This implies that no existing ent in the table has our hash.
4530 * Evict it (updating its chain) and use its ent for head of our chain. */
4531 *new_e = *mainpos_e; /* copies next. */
Chris Fallin91473dc2014-12-12 15:58:26 -08004532 while (chain->next != mainpos_e) {
4533 chain = (upb_tabent*)chain->next;
4534 assert(chain);
4535 }
4536 chain->next = new_e;
4537 our_e = mainpos_e;
4538 our_e->next = NULL;
4539 }
4540 }
Josh Habermane8ed0212015-06-08 17:56:03 -07004541 our_e->key = tabkey;
4542 our_e->val.val = val.val;
Chris Fallin91473dc2014-12-12 15:58:26 -08004543 assert(findentry(t, key, hash, eql) == our_e);
4544}
4545
4546static bool rm(upb_table *t, lookupkey_t key, upb_value *val,
4547 upb_tabkey *removed, uint32_t hash, eqlfunc_t *eql) {
4548 upb_tabent *chain = getentry_mutable(t, hash);
4549 if (upb_tabent_isempty(chain)) return false;
4550 if (eql(chain->key, key)) {
Josh Habermane8ed0212015-06-08 17:56:03 -07004551 /* Element to remove is at the head of its chain. */
Chris Fallin91473dc2014-12-12 15:58:26 -08004552 t->count--;
4553 if (val) {
Josh Habermane8ed0212015-06-08 17:56:03 -07004554 _upb_value_setval(val, chain->val.val, t->ctype);
Chris Fallin91473dc2014-12-12 15:58:26 -08004555 }
4556 if (chain->next) {
4557 upb_tabent *move = (upb_tabent*)chain->next;
4558 *chain = *move;
4559 if (removed) *removed = move->key;
Josh Habermane8ed0212015-06-08 17:56:03 -07004560 move->key = 0; /* Make the slot empty. */
Chris Fallin91473dc2014-12-12 15:58:26 -08004561 } else {
4562 if (removed) *removed = chain->key;
Josh Habermane8ed0212015-06-08 17:56:03 -07004563 chain->key = 0; /* Make the slot empty. */
Chris Fallin91473dc2014-12-12 15:58:26 -08004564 }
4565 return true;
4566 } else {
Josh Habermane8ed0212015-06-08 17:56:03 -07004567 /* Element to remove is either in a non-head position or not in the
4568 * table. */
Chris Fallin91473dc2014-12-12 15:58:26 -08004569 while (chain->next && !eql(chain->next->key, key))
4570 chain = (upb_tabent*)chain->next;
4571 if (chain->next) {
Josh Habermane8ed0212015-06-08 17:56:03 -07004572 /* Found element to remove. */
4573 upb_tabent *rm;
4574
Chris Fallin91473dc2014-12-12 15:58:26 -08004575 if (val) {
Josh Habermane8ed0212015-06-08 17:56:03 -07004576 _upb_value_setval(val, chain->next->val.val, t->ctype);
Chris Fallin91473dc2014-12-12 15:58:26 -08004577 }
Josh Habermane8ed0212015-06-08 17:56:03 -07004578 rm = (upb_tabent*)chain->next;
Chris Fallin91473dc2014-12-12 15:58:26 -08004579 if (removed) *removed = rm->key;
Josh Habermane8ed0212015-06-08 17:56:03 -07004580 rm->key = 0;
Chris Fallin91473dc2014-12-12 15:58:26 -08004581 chain->next = rm->next;
4582 t->count--;
4583 return true;
4584 } else {
4585 return false;
4586 }
4587 }
4588}
4589
4590static size_t next(const upb_table *t, size_t i) {
4591 do {
4592 if (++i >= upb_table_size(t))
4593 return SIZE_MAX;
4594 } while(upb_tabent_isempty(&t->entries[i]));
4595
4596 return i;
4597}
4598
4599static size_t begin(const upb_table *t) {
4600 return next(t, -1);
4601}
4602
4603
4604/* upb_strtable ***************************************************************/
4605
Josh Habermane8ed0212015-06-08 17:56:03 -07004606/* A simple "subclass" of upb_table that only adds a hash function for strings. */
4607
4608static upb_tabkey strcopy(lookupkey_t k2) {
4609 char *str = malloc(k2.str.len + sizeof(uint32_t) + 1);
4610 if (str == NULL) return 0;
4611 memcpy(str, &k2.str.len, sizeof(uint32_t));
4612 memcpy(str + sizeof(uint32_t), k2.str.str, k2.str.len + 1);
4613 return (uintptr_t)str;
4614}
Chris Fallin91473dc2014-12-12 15:58:26 -08004615
4616static uint32_t strhash(upb_tabkey key) {
Josh Habermane8ed0212015-06-08 17:56:03 -07004617 uint32_t len;
4618 char *str = upb_tabstr(key, &len);
4619 return MurmurHash2(str, len, 0);
Chris Fallin91473dc2014-12-12 15:58:26 -08004620}
4621
4622static bool streql(upb_tabkey k1, lookupkey_t k2) {
Josh Habermane8ed0212015-06-08 17:56:03 -07004623 uint32_t len;
4624 char *str = upb_tabstr(k1, &len);
4625 return len == k2.str.len && memcmp(str, k2.str.str, len) == 0;
Chris Fallin91473dc2014-12-12 15:58:26 -08004626}
4627
4628bool upb_strtable_init(upb_strtable *t, upb_ctype_t ctype) {
4629 return init(&t->t, ctype, 2);
4630}
4631
4632void upb_strtable_uninit(upb_strtable *t) {
Josh Habermane8ed0212015-06-08 17:56:03 -07004633 size_t i;
4634 for (i = 0; i < upb_table_size(&t->t); i++)
4635 free((void*)t->t.entries[i].key);
Chris Fallin91473dc2014-12-12 15:58:26 -08004636 uninit(&t->t);
4637}
4638
4639bool upb_strtable_resize(upb_strtable *t, size_t size_lg2) {
4640 upb_strtable new_table;
Josh Habermane8ed0212015-06-08 17:56:03 -07004641 upb_strtable_iter i;
4642
Chris Fallin91473dc2014-12-12 15:58:26 -08004643 if (!init(&new_table.t, t->t.ctype, size_lg2))
4644 return false;
Chris Fallin91473dc2014-12-12 15:58:26 -08004645 upb_strtable_begin(&i, t);
4646 for ( ; !upb_strtable_done(&i); upb_strtable_next(&i)) {
Chris Fallinfd1a3ff2015-01-06 15:44:09 -08004647 upb_strtable_insert2(
4648 &new_table,
4649 upb_strtable_iter_key(&i),
4650 upb_strtable_iter_keylength(&i),
4651 upb_strtable_iter_value(&i));
Chris Fallin91473dc2014-12-12 15:58:26 -08004652 }
4653 upb_strtable_uninit(t);
4654 *t = new_table;
4655 return true;
4656}
4657
Chris Fallinfd1a3ff2015-01-06 15:44:09 -08004658bool upb_strtable_insert2(upb_strtable *t, const char *k, size_t len,
4659 upb_value v) {
Josh Habermane8ed0212015-06-08 17:56:03 -07004660 lookupkey_t key;
4661 upb_tabkey tabkey;
4662 uint32_t hash;
4663
Chris Fallin91473dc2014-12-12 15:58:26 -08004664 if (isfull(&t->t)) {
Josh Habermane8ed0212015-06-08 17:56:03 -07004665 /* Need to resize. New table of double the size, add old elements to it. */
Chris Fallin91473dc2014-12-12 15:58:26 -08004666 if (!upb_strtable_resize(t, t->t.size_lg2 + 1)) {
4667 return false;
4668 }
4669 }
Chris Fallin91473dc2014-12-12 15:58:26 -08004670
Josh Habermane8ed0212015-06-08 17:56:03 -07004671 key = strkey2(k, len);
4672 tabkey = strcopy(key);
4673 if (tabkey == 0) return false;
4674
4675 hash = MurmurHash2(key.str.str, key.str.len, 0);
4676 insert(&t->t, key, tabkey, v, hash, &strhash, &streql);
Chris Fallin91473dc2014-12-12 15:58:26 -08004677 return true;
4678}
4679
4680bool upb_strtable_lookup2(const upb_strtable *t, const char *key, size_t len,
4681 upb_value *v) {
4682 uint32_t hash = MurmurHash2(key, len, 0);
4683 return lookup(&t->t, strkey2(key, len), v, hash, &streql);
4684}
4685
Chris Fallinfd1a3ff2015-01-06 15:44:09 -08004686bool upb_strtable_remove2(upb_strtable *t, const char *key, size_t len,
4687 upb_value *val) {
Chris Fallin91473dc2014-12-12 15:58:26 -08004688 uint32_t hash = MurmurHash2(key, strlen(key), 0);
4689 upb_tabkey tabkey;
Chris Fallinfd1a3ff2015-01-06 15:44:09 -08004690 if (rm(&t->t, strkey2(key, len), val, &tabkey, hash, &streql)) {
Josh Habermane8ed0212015-06-08 17:56:03 -07004691 free((void*)tabkey);
Chris Fallin91473dc2014-12-12 15:58:26 -08004692 return true;
4693 } else {
4694 return false;
4695 }
4696}
4697
Josh Habermane8ed0212015-06-08 17:56:03 -07004698/* Iteration */
Chris Fallin91473dc2014-12-12 15:58:26 -08004699
4700static const upb_tabent *str_tabent(const upb_strtable_iter *i) {
4701 return &i->t->t.entries[i->index];
4702}
4703
4704void upb_strtable_begin(upb_strtable_iter *i, const upb_strtable *t) {
4705 i->t = t;
4706 i->index = begin(&t->t);
4707}
4708
4709void upb_strtable_next(upb_strtable_iter *i) {
4710 i->index = next(&i->t->t, i->index);
4711}
4712
4713bool upb_strtable_done(const upb_strtable_iter *i) {
4714 return i->index >= upb_table_size(&i->t->t) ||
4715 upb_tabent_isempty(str_tabent(i));
4716}
4717
4718const char *upb_strtable_iter_key(upb_strtable_iter *i) {
4719 assert(!upb_strtable_done(i));
Josh Habermane8ed0212015-06-08 17:56:03 -07004720 return upb_tabstr(str_tabent(i)->key, NULL);
Chris Fallinfd1a3ff2015-01-06 15:44:09 -08004721}
4722
4723size_t upb_strtable_iter_keylength(upb_strtable_iter *i) {
Josh Habermane8ed0212015-06-08 17:56:03 -07004724 uint32_t len;
Chris Fallinfd1a3ff2015-01-06 15:44:09 -08004725 assert(!upb_strtable_done(i));
Josh Habermane8ed0212015-06-08 17:56:03 -07004726 upb_tabstr(str_tabent(i)->key, &len);
4727 return len;
Chris Fallin91473dc2014-12-12 15:58:26 -08004728}
4729
4730upb_value upb_strtable_iter_value(const upb_strtable_iter *i) {
4731 assert(!upb_strtable_done(i));
Josh Habermane8ed0212015-06-08 17:56:03 -07004732 return _upb_value_val(str_tabent(i)->val.val, i->t->t.ctype);
Chris Fallin91473dc2014-12-12 15:58:26 -08004733}
4734
4735void upb_strtable_iter_setdone(upb_strtable_iter *i) {
4736 i->index = SIZE_MAX;
4737}
4738
4739bool upb_strtable_iter_isequal(const upb_strtable_iter *i1,
4740 const upb_strtable_iter *i2) {
4741 if (upb_strtable_done(i1) && upb_strtable_done(i2))
4742 return true;
4743 return i1->t == i2->t && i1->index == i2->index;
4744}
4745
4746
4747/* upb_inttable ***************************************************************/
4748
Josh Habermane8ed0212015-06-08 17:56:03 -07004749/* For inttables we use a hybrid structure where small keys are kept in an
4750 * array and large keys are put in the hash table. */
Chris Fallin91473dc2014-12-12 15:58:26 -08004751
Josh Habermane8ed0212015-06-08 17:56:03 -07004752static uint32_t inthash(upb_tabkey key) { return upb_inthash(key); }
Chris Fallin91473dc2014-12-12 15:58:26 -08004753
4754static bool inteql(upb_tabkey k1, lookupkey_t k2) {
Josh Habermane8ed0212015-06-08 17:56:03 -07004755 return k1 == k2.num;
Chris Fallin91473dc2014-12-12 15:58:26 -08004756}
4757
Josh Habermane8ed0212015-06-08 17:56:03 -07004758static upb_tabval *mutable_array(upb_inttable *t) {
4759 return (upb_tabval*)t->array;
Chris Fallin91473dc2014-12-12 15:58:26 -08004760}
4761
Josh Habermane8ed0212015-06-08 17:56:03 -07004762static upb_tabval *inttable_val(upb_inttable *t, uintptr_t key) {
Chris Fallin91473dc2014-12-12 15:58:26 -08004763 if (key < t->array_size) {
4764 return upb_arrhas(t->array[key]) ? &(mutable_array(t)[key]) : NULL;
4765 } else {
4766 upb_tabent *e =
4767 findentry_mutable(&t->t, intkey(key), upb_inthash(key), &inteql);
4768 return e ? &e->val : NULL;
4769 }
4770}
4771
Josh Habermane8ed0212015-06-08 17:56:03 -07004772static const upb_tabval *inttable_val_const(const upb_inttable *t,
Chris Fallin91473dc2014-12-12 15:58:26 -08004773 uintptr_t key) {
4774 return inttable_val((upb_inttable*)t, key);
4775}
4776
4777size_t upb_inttable_count(const upb_inttable *t) {
4778 return t->t.count + t->array_count;
4779}
4780
4781static void check(upb_inttable *t) {
4782 UPB_UNUSED(t);
4783#if defined(UPB_DEBUG_TABLE) && !defined(NDEBUG)
Josh Habermane8ed0212015-06-08 17:56:03 -07004784 {
4785 /* This check is very expensive (makes inserts/deletes O(N)). */
4786 size_t count = 0;
4787 upb_inttable_iter i;
4788 upb_inttable_begin(&i, t);
4789 for(; !upb_inttable_done(&i); upb_inttable_next(&i), count++) {
4790 assert(upb_inttable_lookup(t, upb_inttable_iter_key(&i), NULL));
4791 }
4792 assert(count == upb_inttable_count(t));
Chris Fallin91473dc2014-12-12 15:58:26 -08004793 }
Chris Fallin91473dc2014-12-12 15:58:26 -08004794#endif
4795}
4796
4797bool upb_inttable_sizedinit(upb_inttable *t, upb_ctype_t ctype,
4798 size_t asize, int hsize_lg2) {
Josh Habermane8ed0212015-06-08 17:56:03 -07004799 size_t array_bytes;
4800
Chris Fallin91473dc2014-12-12 15:58:26 -08004801 if (!init(&t->t, ctype, hsize_lg2)) return false;
Josh Habermane8ed0212015-06-08 17:56:03 -07004802 /* Always make the array part at least 1 long, so that we know key 0
4803 * won't be in the hash part, which simplifies things. */
Chris Fallin91473dc2014-12-12 15:58:26 -08004804 t->array_size = UPB_MAX(1, asize);
4805 t->array_count = 0;
Josh Habermane8ed0212015-06-08 17:56:03 -07004806 array_bytes = t->array_size * sizeof(upb_value);
Chris Fallin91473dc2014-12-12 15:58:26 -08004807 t->array = malloc(array_bytes);
4808 if (!t->array) {
4809 uninit(&t->t);
4810 return false;
4811 }
4812 memset(mutable_array(t), 0xff, array_bytes);
4813 check(t);
4814 return true;
4815}
4816
4817bool upb_inttable_init(upb_inttable *t, upb_ctype_t ctype) {
4818 return upb_inttable_sizedinit(t, ctype, 0, 4);
4819}
4820
4821void upb_inttable_uninit(upb_inttable *t) {
4822 uninit(&t->t);
4823 free(mutable_array(t));
4824}
4825
4826bool upb_inttable_insert(upb_inttable *t, uintptr_t key, upb_value val) {
Josh Habermane8ed0212015-06-08 17:56:03 -07004827 /* XXX: Table can't store value (uint64_t)-1. Need to somehow statically
4828 * guarantee that this is not necessary, or fix the limitation. */
4829 upb_tabval tabval;
4830 tabval.val = val.val;
4831 UPB_UNUSED(tabval);
4832 assert(upb_arrhas(tabval));
4833
Chris Fallin91473dc2014-12-12 15:58:26 -08004834 if (key < t->array_size) {
4835 assert(!upb_arrhas(t->array[key]));
4836 t->array_count++;
Josh Habermane8ed0212015-06-08 17:56:03 -07004837 mutable_array(t)[key].val = val.val;
Chris Fallin91473dc2014-12-12 15:58:26 -08004838 } else {
4839 if (isfull(&t->t)) {
Josh Habermane8ed0212015-06-08 17:56:03 -07004840 /* Need to resize the hash part, but we re-use the array part. */
4841 size_t i;
Chris Fallin91473dc2014-12-12 15:58:26 -08004842 upb_table new_table;
4843 if (!init(&new_table, t->t.ctype, t->t.size_lg2 + 1))
4844 return false;
Chris Fallin91473dc2014-12-12 15:58:26 -08004845 for (i = begin(&t->t); i < upb_table_size(&t->t); i = next(&t->t, i)) {
4846 const upb_tabent *e = &t->t.entries[i];
Josh Habermane8ed0212015-06-08 17:56:03 -07004847 uint32_t hash;
Chris Fallin91473dc2014-12-12 15:58:26 -08004848 upb_value v;
Josh Habermane8ed0212015-06-08 17:56:03 -07004849
4850 _upb_value_setval(&v, e->val.val, t->t.ctype);
4851 hash = upb_inthash(e->key);
4852 insert(&new_table, intkey(e->key), e->key, v, hash, &inthash, &inteql);
Chris Fallin91473dc2014-12-12 15:58:26 -08004853 }
4854
4855 assert(t->t.count == new_table.count);
4856
4857 uninit(&t->t);
4858 t->t = new_table;
4859 }
Josh Habermane8ed0212015-06-08 17:56:03 -07004860 insert(&t->t, intkey(key), key, val, upb_inthash(key), &inthash, &inteql);
Chris Fallin91473dc2014-12-12 15:58:26 -08004861 }
4862 check(t);
4863 return true;
4864}
4865
4866bool upb_inttable_lookup(const upb_inttable *t, uintptr_t key, upb_value *v) {
Josh Habermane8ed0212015-06-08 17:56:03 -07004867 const upb_tabval *table_v = inttable_val_const(t, key);
Chris Fallin91473dc2014-12-12 15:58:26 -08004868 if (!table_v) return false;
Josh Habermane8ed0212015-06-08 17:56:03 -07004869 if (v) _upb_value_setval(v, table_v->val, t->t.ctype);
Chris Fallin91473dc2014-12-12 15:58:26 -08004870 return true;
4871}
4872
4873bool upb_inttable_replace(upb_inttable *t, uintptr_t key, upb_value val) {
Josh Habermane8ed0212015-06-08 17:56:03 -07004874 upb_tabval *table_v = inttable_val(t, key);
Chris Fallin91473dc2014-12-12 15:58:26 -08004875 if (!table_v) return false;
Josh Habermane8ed0212015-06-08 17:56:03 -07004876 table_v->val = val.val;
Chris Fallin91473dc2014-12-12 15:58:26 -08004877 return true;
4878}
4879
4880bool upb_inttable_remove(upb_inttable *t, uintptr_t key, upb_value *val) {
4881 bool success;
4882 if (key < t->array_size) {
4883 if (upb_arrhas(t->array[key])) {
Josh Habermane8ed0212015-06-08 17:56:03 -07004884 upb_tabval empty = UPB_TABVALUE_EMPTY_INIT;
Chris Fallin91473dc2014-12-12 15:58:26 -08004885 t->array_count--;
4886 if (val) {
Josh Habermane8ed0212015-06-08 17:56:03 -07004887 _upb_value_setval(val, t->array[key].val, t->t.ctype);
Chris Fallin91473dc2014-12-12 15:58:26 -08004888 }
Chris Fallin91473dc2014-12-12 15:58:26 -08004889 mutable_array(t)[key] = empty;
4890 success = true;
4891 } else {
4892 success = false;
4893 }
4894 } else {
4895 upb_tabkey removed;
4896 uint32_t hash = upb_inthash(key);
4897 success = rm(&t->t, intkey(key), val, &removed, hash, &inteql);
4898 }
4899 check(t);
4900 return success;
4901}
4902
4903bool upb_inttable_push(upb_inttable *t, upb_value val) {
4904 return upb_inttable_insert(t, upb_inttable_count(t), val);
4905}
4906
4907upb_value upb_inttable_pop(upb_inttable *t) {
4908 upb_value val;
4909 bool ok = upb_inttable_remove(t, upb_inttable_count(t) - 1, &val);
4910 UPB_ASSERT_VAR(ok, ok);
4911 return val;
4912}
4913
4914bool upb_inttable_insertptr(upb_inttable *t, const void *key, upb_value val) {
4915 return upb_inttable_insert(t, (uintptr_t)key, val);
4916}
4917
4918bool upb_inttable_lookupptr(const upb_inttable *t, const void *key,
4919 upb_value *v) {
4920 return upb_inttable_lookup(t, (uintptr_t)key, v);
4921}
4922
4923bool upb_inttable_removeptr(upb_inttable *t, const void *key, upb_value *val) {
4924 return upb_inttable_remove(t, (uintptr_t)key, val);
4925}
4926
4927void upb_inttable_compact(upb_inttable *t) {
Josh Habermanf654d492016-02-18 11:07:51 -08004928 /* A power-of-two histogram of the table keys. */
4929 size_t counts[UPB_MAXARRSIZE + 1] = {0};
4930
4931 /* The max key in each bucket. */
4932 uintptr_t max[UPB_MAXARRSIZE + 1] = {0};
4933
Chris Fallin91473dc2014-12-12 15:58:26 -08004934 upb_inttable_iter i;
Josh Habermanf654d492016-02-18 11:07:51 -08004935 size_t arr_count;
4936 int size_lg2;
Josh Habermane8ed0212015-06-08 17:56:03 -07004937 upb_inttable new_t;
4938
Chris Fallin91473dc2014-12-12 15:58:26 -08004939 upb_inttable_begin(&i, t);
4940 for (; !upb_inttable_done(&i); upb_inttable_next(&i)) {
4941 uintptr_t key = upb_inttable_iter_key(&i);
Josh Habermanf654d492016-02-18 11:07:51 -08004942 int bucket = log2ceil(key);
4943 max[bucket] = UPB_MAX(max[bucket], key);
4944 counts[bucket]++;
Chris Fallin91473dc2014-12-12 15:58:26 -08004945 }
4946
Josh Habermanf654d492016-02-18 11:07:51 -08004947 /* Find the largest power of two that satisfies the MIN_DENSITY
4948 * definition (while actually having some keys). */
Josh Habermane8ed0212015-06-08 17:56:03 -07004949 arr_count = upb_inttable_count(t);
Chris Fallin91473dc2014-12-12 15:58:26 -08004950
Josh Habermanf654d492016-02-18 11:07:51 -08004951 for (size_lg2 = ARRAY_SIZE(counts) - 1; size_lg2 > 0; size_lg2--) {
4952 if (counts[size_lg2] == 0) {
4953 /* We can halve again without losing any entries. */
4954 continue;
4955 } else if (arr_count >= (1 << size_lg2) * MIN_DENSITY) {
4956 break;
Chris Fallin91473dc2014-12-12 15:58:26 -08004957 }
Josh Habermanf654d492016-02-18 11:07:51 -08004958
4959 arr_count -= counts[size_lg2];
Chris Fallin91473dc2014-12-12 15:58:26 -08004960 }
4961
Josh Habermanf654d492016-02-18 11:07:51 -08004962 assert(arr_count <= upb_inttable_count(t));
Chris Fallin91473dc2014-12-12 15:58:26 -08004963
Josh Habermane8ed0212015-06-08 17:56:03 -07004964 {
4965 /* Insert all elements into new, perfectly-sized table. */
Josh Habermanf654d492016-02-18 11:07:51 -08004966 size_t arr_size = max[size_lg2] + 1; /* +1 so arr[max] will fit. */
4967 size_t hash_count = upb_inttable_count(t) - arr_count;
4968 size_t hash_size = hash_count ? (hash_count / MAX_LOAD) + 1 : 0;
4969 size_t hashsize_lg2 = log2ceil(hash_size);
Chris Fallin91473dc2014-12-12 15:58:26 -08004970
Josh Habermane8ed0212015-06-08 17:56:03 -07004971 upb_inttable_sizedinit(&new_t, t->t.ctype, arr_size, hashsize_lg2);
4972 upb_inttable_begin(&i, t);
4973 for (; !upb_inttable_done(&i); upb_inttable_next(&i)) {
4974 uintptr_t k = upb_inttable_iter_key(&i);
4975 upb_inttable_insert(&new_t, k, upb_inttable_iter_value(&i));
4976 }
4977 assert(new_t.array_size == arr_size);
4978 assert(new_t.t.size_lg2 == hashsize_lg2);
Chris Fallin91473dc2014-12-12 15:58:26 -08004979 }
Chris Fallin91473dc2014-12-12 15:58:26 -08004980 upb_inttable_uninit(t);
4981 *t = new_t;
4982}
4983
Josh Habermane8ed0212015-06-08 17:56:03 -07004984/* Iteration. */
Chris Fallin91473dc2014-12-12 15:58:26 -08004985
4986static const upb_tabent *int_tabent(const upb_inttable_iter *i) {
4987 assert(!i->array_part);
4988 return &i->t->t.entries[i->index];
4989}
4990
Josh Habermane8ed0212015-06-08 17:56:03 -07004991static upb_tabval int_arrent(const upb_inttable_iter *i) {
Chris Fallin91473dc2014-12-12 15:58:26 -08004992 assert(i->array_part);
4993 return i->t->array[i->index];
4994}
4995
4996void upb_inttable_begin(upb_inttable_iter *i, const upb_inttable *t) {
4997 i->t = t;
4998 i->index = -1;
4999 i->array_part = true;
5000 upb_inttable_next(i);
5001}
5002
5003void upb_inttable_next(upb_inttable_iter *iter) {
5004 const upb_inttable *t = iter->t;
5005 if (iter->array_part) {
5006 while (++iter->index < t->array_size) {
5007 if (upb_arrhas(int_arrent(iter))) {
5008 return;
5009 }
5010 }
5011 iter->array_part = false;
5012 iter->index = begin(&t->t);
5013 } else {
5014 iter->index = next(&t->t, iter->index);
5015 }
5016}
5017
5018bool upb_inttable_done(const upb_inttable_iter *i) {
5019 if (i->array_part) {
5020 return i->index >= i->t->array_size ||
5021 !upb_arrhas(int_arrent(i));
5022 } else {
5023 return i->index >= upb_table_size(&i->t->t) ||
5024 upb_tabent_isempty(int_tabent(i));
5025 }
5026}
5027
5028uintptr_t upb_inttable_iter_key(const upb_inttable_iter *i) {
5029 assert(!upb_inttable_done(i));
Josh Habermane8ed0212015-06-08 17:56:03 -07005030 return i->array_part ? i->index : int_tabent(i)->key;
Chris Fallin91473dc2014-12-12 15:58:26 -08005031}
5032
5033upb_value upb_inttable_iter_value(const upb_inttable_iter *i) {
5034 assert(!upb_inttable_done(i));
5035 return _upb_value_val(
Josh Habermane8ed0212015-06-08 17:56:03 -07005036 i->array_part ? i->t->array[i->index].val : int_tabent(i)->val.val,
Chris Fallin91473dc2014-12-12 15:58:26 -08005037 i->t->t.ctype);
5038}
5039
5040void upb_inttable_iter_setdone(upb_inttable_iter *i) {
5041 i->index = SIZE_MAX;
5042 i->array_part = false;
5043}
5044
5045bool upb_inttable_iter_isequal(const upb_inttable_iter *i1,
5046 const upb_inttable_iter *i2) {
5047 if (upb_inttable_done(i1) && upb_inttable_done(i2))
5048 return true;
5049 return i1->t == i2->t && i1->index == i2->index &&
5050 i1->array_part == i2->array_part;
5051}
5052
5053#ifdef UPB_UNALIGNED_READS_OK
Josh Habermane8ed0212015-06-08 17:56:03 -07005054/* -----------------------------------------------------------------------------
5055 * MurmurHash2, by Austin Appleby (released as public domain).
5056 * Reformatted and C99-ified by Joshua Haberman.
5057 * Note - This code makes a few assumptions about how your machine behaves -
5058 * 1. We can read a 4-byte value from any address without crashing
5059 * 2. sizeof(int) == 4 (in upb this limitation is removed by using uint32_t
5060 * And it has a few limitations -
5061 * 1. It will not work incrementally.
5062 * 2. It will not produce the same results on little-endian and big-endian
5063 * machines. */
Chris Fallin91473dc2014-12-12 15:58:26 -08005064uint32_t MurmurHash2(const void *key, size_t len, uint32_t seed) {
Josh Habermane8ed0212015-06-08 17:56:03 -07005065 /* 'm' and 'r' are mixing constants generated offline.
5066 * They're not really 'magic', they just happen to work well. */
Chris Fallin91473dc2014-12-12 15:58:26 -08005067 const uint32_t m = 0x5bd1e995;
5068 const int32_t r = 24;
5069
Josh Habermane8ed0212015-06-08 17:56:03 -07005070 /* Initialize the hash to a 'random' value */
Chris Fallin91473dc2014-12-12 15:58:26 -08005071 uint32_t h = seed ^ len;
5072
Josh Habermane8ed0212015-06-08 17:56:03 -07005073 /* Mix 4 bytes at a time into the hash */
Chris Fallin91473dc2014-12-12 15:58:26 -08005074 const uint8_t * data = (const uint8_t *)key;
5075 while(len >= 4) {
5076 uint32_t k = *(uint32_t *)data;
5077
5078 k *= m;
5079 k ^= k >> r;
5080 k *= m;
5081
5082 h *= m;
5083 h ^= k;
5084
5085 data += 4;
5086 len -= 4;
5087 }
5088
Josh Habermane8ed0212015-06-08 17:56:03 -07005089 /* Handle the last few bytes of the input array */
Chris Fallin91473dc2014-12-12 15:58:26 -08005090 switch(len) {
5091 case 3: h ^= data[2] << 16;
5092 case 2: h ^= data[1] << 8;
5093 case 1: h ^= data[0]; h *= m;
5094 };
5095
Josh Habermane8ed0212015-06-08 17:56:03 -07005096 /* Do a few final mixes of the hash to ensure the last few
5097 * bytes are well-incorporated. */
Chris Fallin91473dc2014-12-12 15:58:26 -08005098 h ^= h >> 13;
5099 h *= m;
5100 h ^= h >> 15;
5101
5102 return h;
5103}
5104
Josh Habermane8ed0212015-06-08 17:56:03 -07005105#else /* !UPB_UNALIGNED_READS_OK */
Chris Fallin91473dc2014-12-12 15:58:26 -08005106
Josh Habermane8ed0212015-06-08 17:56:03 -07005107/* -----------------------------------------------------------------------------
5108 * MurmurHashAligned2, by Austin Appleby
5109 * Same algorithm as MurmurHash2, but only does aligned reads - should be safer
5110 * on certain platforms.
5111 * Performance will be lower than MurmurHash2 */
Chris Fallin91473dc2014-12-12 15:58:26 -08005112
5113#define MIX(h,k,m) { k *= m; k ^= k >> r; k *= m; h *= m; h ^= k; }
5114
5115uint32_t MurmurHash2(const void * key, size_t len, uint32_t seed) {
5116 const uint32_t m = 0x5bd1e995;
5117 const int32_t r = 24;
5118 const uint8_t * data = (const uint8_t *)key;
5119 uint32_t h = seed ^ len;
5120 uint8_t align = (uintptr_t)data & 3;
5121
5122 if(align && (len >= 4)) {
Josh Habermane8ed0212015-06-08 17:56:03 -07005123 /* Pre-load the temp registers */
Chris Fallin91473dc2014-12-12 15:58:26 -08005124 uint32_t t = 0, d = 0;
Josh Habermane8ed0212015-06-08 17:56:03 -07005125 int32_t sl;
5126 int32_t sr;
Chris Fallin91473dc2014-12-12 15:58:26 -08005127
5128 switch(align) {
5129 case 1: t |= data[2] << 16;
5130 case 2: t |= data[1] << 8;
5131 case 3: t |= data[0];
5132 }
5133
5134 t <<= (8 * align);
5135
5136 data += 4-align;
5137 len -= 4-align;
5138
Josh Habermane8ed0212015-06-08 17:56:03 -07005139 sl = 8 * (4-align);
5140 sr = 8 * align;
Chris Fallin91473dc2014-12-12 15:58:26 -08005141
Josh Habermane8ed0212015-06-08 17:56:03 -07005142 /* Mix */
Chris Fallin91473dc2014-12-12 15:58:26 -08005143
5144 while(len >= 4) {
Josh Habermane8ed0212015-06-08 17:56:03 -07005145 uint32_t k;
5146
Chris Fallin91473dc2014-12-12 15:58:26 -08005147 d = *(uint32_t *)data;
5148 t = (t >> sr) | (d << sl);
5149
Josh Habermane8ed0212015-06-08 17:56:03 -07005150 k = t;
Chris Fallin91473dc2014-12-12 15:58:26 -08005151
5152 MIX(h,k,m);
5153
5154 t = d;
5155
5156 data += 4;
5157 len -= 4;
5158 }
5159
Josh Habermane8ed0212015-06-08 17:56:03 -07005160 /* Handle leftover data in temp registers */
Chris Fallin91473dc2014-12-12 15:58:26 -08005161
5162 d = 0;
5163
5164 if(len >= align) {
Josh Habermane8ed0212015-06-08 17:56:03 -07005165 uint32_t k;
5166
Chris Fallin91473dc2014-12-12 15:58:26 -08005167 switch(align) {
5168 case 3: d |= data[2] << 16;
5169 case 2: d |= data[1] << 8;
5170 case 1: d |= data[0];
5171 }
5172
Josh Habermane8ed0212015-06-08 17:56:03 -07005173 k = (t >> sr) | (d << sl);
Chris Fallin91473dc2014-12-12 15:58:26 -08005174 MIX(h,k,m);
5175
5176 data += align;
5177 len -= align;
5178
Josh Habermane8ed0212015-06-08 17:56:03 -07005179 /* ----------
5180 * Handle tail bytes */
Chris Fallin91473dc2014-12-12 15:58:26 -08005181
5182 switch(len) {
5183 case 3: h ^= data[2] << 16;
5184 case 2: h ^= data[1] << 8;
5185 case 1: h ^= data[0]; h *= m;
5186 };
5187 } else {
5188 switch(len) {
5189 case 3: d |= data[2] << 16;
5190 case 2: d |= data[1] << 8;
5191 case 1: d |= data[0];
5192 case 0: h ^= (t >> sr) | (d << sl); h *= m;
5193 }
5194 }
5195
5196 h ^= h >> 13;
5197 h *= m;
5198 h ^= h >> 15;
5199
5200 return h;
5201 } else {
5202 while(len >= 4) {
5203 uint32_t k = *(uint32_t *)data;
5204
5205 MIX(h,k,m);
5206
5207 data += 4;
5208 len -= 4;
5209 }
5210
Josh Habermane8ed0212015-06-08 17:56:03 -07005211 /* ----------
5212 * Handle tail bytes */
Chris Fallin91473dc2014-12-12 15:58:26 -08005213
5214 switch(len) {
5215 case 3: h ^= data[2] << 16;
5216 case 2: h ^= data[1] << 8;
5217 case 1: h ^= data[0]; h *= m;
5218 };
5219
5220 h ^= h >> 13;
5221 h *= m;
5222 h ^= h >> 15;
5223
5224 return h;
5225 }
5226}
5227#undef MIX
5228
Josh Habermane8ed0212015-06-08 17:56:03 -07005229#endif /* UPB_UNALIGNED_READS_OK */
Chris Fallin91473dc2014-12-12 15:58:26 -08005230
5231#include <errno.h>
5232#include <stdarg.h>
5233#include <stddef.h>
5234#include <stdint.h>
5235#include <stdio.h>
5236#include <stdlib.h>
5237#include <string.h>
5238
5239bool upb_dumptostderr(void *closure, const upb_status* status) {
5240 UPB_UNUSED(closure);
5241 fprintf(stderr, "%s\n", upb_status_errmsg(status));
5242 return false;
5243}
5244
Josh Habermane8ed0212015-06-08 17:56:03 -07005245/* Guarantee null-termination and provide ellipsis truncation.
5246 * It may be tempting to "optimize" this by initializing these final
5247 * four bytes up-front and then being careful never to overwrite them,
5248 * this is safer and simpler. */
Chris Fallin91473dc2014-12-12 15:58:26 -08005249static void nullz(upb_status *status) {
5250 const char *ellipsis = "...";
5251 size_t len = strlen(ellipsis);
5252 assert(sizeof(status->msg) > len);
5253 memcpy(status->msg + sizeof(status->msg) - len, ellipsis, len);
5254}
5255
5256void upb_status_clear(upb_status *status) {
Chris Fallin97b663a2015-01-09 16:15:22 -08005257 if (!status) return;
5258 status->ok_ = true;
5259 status->code_ = 0;
5260 status->msg[0] = '\0';
Chris Fallin91473dc2014-12-12 15:58:26 -08005261}
5262
5263bool upb_ok(const upb_status *status) { return status->ok_; }
5264
5265upb_errorspace *upb_status_errspace(const upb_status *status) {
5266 return status->error_space_;
5267}
5268
5269int upb_status_errcode(const upb_status *status) { return status->code_; }
5270
5271const char *upb_status_errmsg(const upb_status *status) { return status->msg; }
5272
5273void upb_status_seterrmsg(upb_status *status, const char *msg) {
5274 if (!status) return;
5275 status->ok_ = false;
5276 strncpy(status->msg, msg, sizeof(status->msg));
5277 nullz(status);
5278}
5279
5280void upb_status_seterrf(upb_status *status, const char *fmt, ...) {
5281 va_list args;
5282 va_start(args, fmt);
5283 upb_status_vseterrf(status, fmt, args);
5284 va_end(args);
5285}
5286
5287void upb_status_vseterrf(upb_status *status, const char *fmt, va_list args) {
5288 if (!status) return;
5289 status->ok_ = false;
Josh Habermane8ed0212015-06-08 17:56:03 -07005290 _upb_vsnprintf(status->msg, sizeof(status->msg), fmt, args);
Chris Fallin91473dc2014-12-12 15:58:26 -08005291 nullz(status);
5292}
5293
5294void upb_status_seterrcode(upb_status *status, upb_errorspace *space,
5295 int code) {
5296 if (!status) return;
5297 status->ok_ = false;
5298 status->error_space_ = space;
5299 status->code_ = code;
5300 space->set_message(status, code);
5301}
5302
5303void upb_status_copy(upb_status *to, const upb_status *from) {
5304 if (!to) return;
5305 *to = *from;
5306}
Josh Habermane8ed0212015-06-08 17:56:03 -07005307/* This file was generated by upbc (the upb compiler).
5308 * Do not edit -- your changes will be discarded when the file is
5309 * regenerated. */
Chris Fallin91473dc2014-12-12 15:58:26 -08005310
Josh Haberman94e54b32016-04-14 12:06:09 -07005311#include <assert.h>
5312
Chris Fallin91473dc2014-12-12 15:58:26 -08005313
Josh Haberman78da6662016-01-13 19:05:43 -08005314static const upb_msgdef msgs[22];
5315static const upb_fielddef fields[105];
5316static const upb_enumdef enums[5];
Josh Haberman94e54b32016-04-14 12:06:09 -07005317static const upb_tabent strentries[236];
Josh Haberman78da6662016-01-13 19:05:43 -08005318static const upb_tabent intentries[18];
Josh Habermanf654d492016-02-18 11:07:51 -08005319static const upb_tabval arrays[184];
Chris Fallin91473dc2014-12-12 15:58:26 -08005320
5321#ifdef UPB_DEBUG_REFS
Josh Haberman94e54b32016-04-14 12:06:09 -07005322static upb_inttable reftables[264];
Chris Fallin91473dc2014-12-12 15:58:26 -08005323#endif
5324
Josh Haberman78da6662016-01-13 19:05:43 -08005325static const upb_msgdef msgs[22] = {
5326 UPB_MSGDEF_INIT("google.protobuf.DescriptorProto", 40, 8, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[0], 11, 10), UPB_STRTABLE_INIT(10, 15, UPB_CTYPE_PTR, 4, &strentries[0]),&reftables[0], &reftables[1]),
5327 UPB_MSGDEF_INIT("google.protobuf.DescriptorProto.ExtensionRange", 4, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[11], 3, 2), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[16]),&reftables[2], &reftables[3]),
5328 UPB_MSGDEF_INIT("google.protobuf.DescriptorProto.ReservedRange", 4, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[14], 3, 2), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[20]),&reftables[4], &reftables[5]),
5329 UPB_MSGDEF_INIT("google.protobuf.EnumDescriptorProto", 11, 2, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[17], 4, 3), UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_PTR, 2, &strentries[24]),&reftables[6], &reftables[7]),
Josh Habermanf654d492016-02-18 11:07:51 -08005330 UPB_MSGDEF_INIT("google.protobuf.EnumOptions", 8, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[0], &arrays[21], 4, 2), UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_PTR, 2, &strentries[28]),&reftables[8], &reftables[9]),
5331 UPB_MSGDEF_INIT("google.protobuf.EnumValueDescriptorProto", 8, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[25], 4, 3), UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_PTR, 2, &strentries[32]),&reftables[10], &reftables[11]),
5332 UPB_MSGDEF_INIT("google.protobuf.EnumValueOptions", 7, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[2], &arrays[29], 2, 1), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[36]),&reftables[12], &reftables[13]),
5333 UPB_MSGDEF_INIT("google.protobuf.FieldDescriptorProto", 23, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[31], 11, 10), UPB_STRTABLE_INIT(10, 15, UPB_CTYPE_PTR, 4, &strentries[40]),&reftables[14], &reftables[15]),
5334 UPB_MSGDEF_INIT("google.protobuf.FieldOptions", 12, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[4], &arrays[42], 11, 6), UPB_STRTABLE_INIT(7, 15, UPB_CTYPE_PTR, 4, &strentries[56]),&reftables[16], &reftables[17]),
5335 UPB_MSGDEF_INIT("google.protobuf.FileDescriptorProto", 42, 6, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[53], 13, 12), UPB_STRTABLE_INIT(12, 15, UPB_CTYPE_PTR, 4, &strentries[72]),&reftables[18], &reftables[19]),
5336 UPB_MSGDEF_INIT("google.protobuf.FileDescriptorSet", 6, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[66], 2, 1), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &strentries[88]),&reftables[20], &reftables[21]),
5337 UPB_MSGDEF_INIT("google.protobuf.FileOptions", 31, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[6], &arrays[68], 39, 15), UPB_STRTABLE_INIT(16, 31, UPB_CTYPE_PTR, 5, &strentries[92]),&reftables[22], &reftables[23]),
5338 UPB_MSGDEF_INIT("google.protobuf.MessageOptions", 10, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[8], &arrays[107], 8, 4), UPB_STRTABLE_INIT(5, 7, UPB_CTYPE_PTR, 3, &strentries[124]),&reftables[24], &reftables[25]),
5339 UPB_MSGDEF_INIT("google.protobuf.MethodDescriptorProto", 15, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[115], 7, 6), UPB_STRTABLE_INIT(6, 7, UPB_CTYPE_PTR, 3, &strentries[132]),&reftables[26], &reftables[27]),
5340 UPB_MSGDEF_INIT("google.protobuf.MethodOptions", 7, 1, UPB_INTTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &intentries[10], &arrays[122], 1, 0), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[140]),&reftables[28], &reftables[29]),
5341 UPB_MSGDEF_INIT("google.protobuf.OneofDescriptorProto", 5, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[123], 2, 1), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &strentries[144]),&reftables[30], &reftables[31]),
5342 UPB_MSGDEF_INIT("google.protobuf.ServiceDescriptorProto", 11, 2, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[125], 4, 3), UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_PTR, 2, &strentries[148]),&reftables[32], &reftables[33]),
5343 UPB_MSGDEF_INIT("google.protobuf.ServiceOptions", 7, 1, UPB_INTTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &intentries[14], &arrays[129], 1, 0), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[152]),&reftables[34], &reftables[35]),
5344 UPB_MSGDEF_INIT("google.protobuf.SourceCodeInfo", 6, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[130], 2, 1), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &strentries[156]),&reftables[36], &reftables[37]),
5345 UPB_MSGDEF_INIT("google.protobuf.SourceCodeInfo.Location", 19, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[132], 7, 5), UPB_STRTABLE_INIT(5, 7, UPB_CTYPE_PTR, 3, &strentries[160]),&reftables[38], &reftables[39]),
5346 UPB_MSGDEF_INIT("google.protobuf.UninterpretedOption", 18, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[139], 9, 7), UPB_STRTABLE_INIT(7, 15, UPB_CTYPE_PTR, 4, &strentries[168]),&reftables[40], &reftables[41]),
5347 UPB_MSGDEF_INIT("google.protobuf.UninterpretedOption.NamePart", 6, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[148], 3, 2), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[184]),&reftables[42], &reftables[43]),
Chris Fallin91473dc2014-12-12 15:58:26 -08005348};
5349
Josh Haberman78da6662016-01-13 19:05:43 -08005350static const upb_fielddef fields[105] = {
5351 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "aggregate_value", 8, &msgs[20], NULL, 15, 6, {0},&reftables[44], &reftables[45]),
5352 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "allow_alias", 2, &msgs[4], NULL, 6, 1, {0},&reftables[46], &reftables[47]),
5353 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "cc_enable_arenas", 31, &msgs[11], NULL, 23, 12, {0},&reftables[48], &reftables[49]),
5354 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "cc_generic_services", 16, &msgs[11], NULL, 17, 6, {0},&reftables[50], &reftables[51]),
5355 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "client_streaming", 5, &msgs[13], NULL, 13, 4, {0},&reftables[52], &reftables[53]),
5356 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "csharp_namespace", 37, &msgs[11], NULL, 27, 14, {0},&reftables[54], &reftables[55]),
5357 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, false, "ctype", 1, &msgs[8], (const upb_def*)(&enums[2]), 6, 1, {0},&reftables[56], &reftables[57]),
5358 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "default_value", 7, &msgs[7], NULL, 16, 7, {0},&reftables[58], &reftables[59]),
5359 UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_STRING, 0, false, false, false, false, "dependency", 3, &msgs[9], NULL, 30, 8, {0},&reftables[60], &reftables[61]),
Josh Haberman94e54b32016-04-14 12:06:09 -07005360 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 3, &msgs[12], NULL, 8, 3, {0},&reftables[62], &reftables[63]),
5361 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 3, &msgs[8], NULL, 8, 3, {0},&reftables[64], &reftables[65]),
5362 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 33, &msgs[14], NULL, 6, 1, {0},&reftables[66], &reftables[67]),
5363 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 23, &msgs[11], NULL, 21, 10, {0},&reftables[68], &reftables[69]),
5364 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 3, &msgs[4], NULL, 7, 2, {0},&reftables[70], &reftables[71]),
5365 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 33, &msgs[17], NULL, 6, 1, {0},&reftables[72], &reftables[73]),
5366 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 1, &msgs[6], NULL, 6, 1, {0},&reftables[74], &reftables[75]),
Josh Haberman78da6662016-01-13 19:05:43 -08005367 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_DOUBLE, 0, false, false, false, false, "double_value", 6, &msgs[20], NULL, 11, 4, {0},&reftables[76], &reftables[77]),
5368 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "end", 2, &msgs[2], NULL, 3, 1, {0},&reftables[78], &reftables[79]),
5369 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "end", 2, &msgs[1], NULL, 3, 1, {0},&reftables[80], &reftables[81]),
Josh Haberman94e54b32016-04-14 12:06:09 -07005370 UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "enum_type", 4, &msgs[0], (const upb_def*)(&msgs[3]), 18, 2, {0},&reftables[82], &reftables[83]),
5371 UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "enum_type", 5, &msgs[9], (const upb_def*)(&msgs[3]), 13, 1, {0},&reftables[84], &reftables[85]),
Josh Haberman78da6662016-01-13 19:05:43 -08005372 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "extendee", 2, &msgs[7], NULL, 7, 2, {0},&reftables[86], &reftables[87]),
5373 UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "extension", 6, &msgs[0], (const upb_def*)(&msgs[7]), 24, 4, {0},&reftables[88], &reftables[89]),
5374 UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "extension", 7, &msgs[9], (const upb_def*)(&msgs[7]), 19, 3, {0},&reftables[90], &reftables[91]),
5375 UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "extension_range", 5, &msgs[0], (const upb_def*)(&msgs[1]), 21, 3, {0},&reftables[92], &reftables[93]),
5376 UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "field", 2, &msgs[0], (const upb_def*)(&msgs[7]), 12, 0, {0},&reftables[94], &reftables[95]),
5377 UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "file", 1, &msgs[10], (const upb_def*)(&msgs[9]), 5, 0, {0},&reftables[96], &reftables[97]),
5378 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "go_package", 11, &msgs[11], NULL, 14, 5, {0},&reftables[98], &reftables[99]),
5379 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "identifier_value", 3, &msgs[20], NULL, 6, 1, {0},&reftables[100], &reftables[101]),
5380 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "input_type", 2, &msgs[13], NULL, 7, 2, {0},&reftables[102], &reftables[103]),
5381 UPB_FIELDDEF_INIT(UPB_LABEL_REQUIRED, UPB_TYPE_BOOL, 0, false, false, false, false, "is_extension", 2, &msgs[21], NULL, 5, 1, {0},&reftables[104], &reftables[105]),
5382 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "java_generate_equals_and_hash", 20, &msgs[11], NULL, 20, 9, {0},&reftables[106], &reftables[107]),
5383 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "java_generic_services", 17, &msgs[11], NULL, 18, 7, {0},&reftables[108], &reftables[109]),
5384 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "java_multiple_files", 10, &msgs[11], NULL, 13, 4, {0},&reftables[110], &reftables[111]),
5385 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "java_outer_classname", 8, &msgs[11], NULL, 9, 2, {0},&reftables[112], &reftables[113]),
5386 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "java_package", 1, &msgs[11], NULL, 6, 1, {0},&reftables[114], &reftables[115]),
5387 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "java_string_check_utf8", 27, &msgs[11], NULL, 22, 11, {0},&reftables[116], &reftables[117]),
5388 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "javanano_use_deprecated_package", 38, &msgs[11], NULL, 30, 15, {0},&reftables[118], &reftables[119]),
5389 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "json_name", 10, &msgs[7], NULL, 20, 9, {0},&reftables[120], &reftables[121]),
5390 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, false, "jstype", 6, &msgs[8], (const upb_def*)(&enums[3]), 10, 5, {0},&reftables[122], &reftables[123]),
5391 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, false, "label", 4, &msgs[7], (const upb_def*)(&enums[0]), 11, 4, {0},&reftables[124], &reftables[125]),
5392 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "lazy", 5, &msgs[8], NULL, 9, 4, {0},&reftables[126], &reftables[127]),
5393 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "leading_comments", 3, &msgs[19], NULL, 8, 2, {0},&reftables[128], &reftables[129]),
5394 UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_STRING, 0, false, false, false, false, "leading_detached_comments", 6, &msgs[19], NULL, 16, 4, {0},&reftables[130], &reftables[131]),
5395 UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "location", 1, &msgs[18], (const upb_def*)(&msgs[19]), 5, 0, {0},&reftables[132], &reftables[133]),
5396 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "map_entry", 7, &msgs[12], NULL, 9, 4, {0},&reftables[134], &reftables[135]),
5397 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "message_set_wire_format", 1, &msgs[12], NULL, 6, 1, {0},&reftables[136], &reftables[137]),
5398 UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "message_type", 4, &msgs[9], (const upb_def*)(&msgs[0]), 10, 0, {0},&reftables[138], &reftables[139]),
5399 UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "method", 2, &msgs[16], (const upb_def*)(&msgs[13]), 6, 0, {0},&reftables[140], &reftables[141]),
Josh Haberman94e54b32016-04-14 12:06:09 -07005400 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[3], NULL, 8, 2, {0},&reftables[142], &reftables[143]),
5401 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[15], NULL, 2, 0, {0},&reftables[144], &reftables[145]),
5402 UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "name", 2, &msgs[20], (const upb_def*)(&msgs[21]), 5, 0, {0},&reftables[146], &reftables[147]),
Josh Haberman78da6662016-01-13 19:05:43 -08005403 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[0], NULL, 32, 8, {0},&reftables[148], &reftables[149]),
Josh Haberman94e54b32016-04-14 12:06:09 -07005404 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[5], NULL, 4, 1, {0},&reftables[150], &reftables[151]),
5405 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[9], NULL, 22, 6, {0},&reftables[152], &reftables[153]),
5406 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[7], NULL, 4, 1, {0},&reftables[154], &reftables[155]),
5407 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[13], NULL, 4, 1, {0},&reftables[156], &reftables[157]),
5408 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[16], NULL, 8, 2, {0},&reftables[158], &reftables[159]),
Josh Haberman78da6662016-01-13 19:05:43 -08005409 UPB_FIELDDEF_INIT(UPB_LABEL_REQUIRED, UPB_TYPE_STRING, 0, false, false, false, false, "name_part", 1, &msgs[21], NULL, 2, 0, {0},&reftables[160], &reftables[161]),
5410 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT64, UPB_INTFMT_VARIABLE, false, false, false, false, "negative_int_value", 5, &msgs[20], NULL, 10, 3, {0},&reftables[162], &reftables[163]),
5411 UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "nested_type", 3, &msgs[0], (const upb_def*)(&msgs[0]), 15, 1, {0},&reftables[164], &reftables[165]),
5412 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "no_standard_descriptor_accessor", 2, &msgs[12], NULL, 7, 2, {0},&reftables[166], &reftables[167]),
Josh Haberman94e54b32016-04-14 12:06:09 -07005413 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "number", 2, &msgs[5], NULL, 7, 2, {0},&reftables[168], &reftables[169]),
5414 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "number", 3, &msgs[7], NULL, 10, 3, {0},&reftables[170], &reftables[171]),
Josh Haberman78da6662016-01-13 19:05:43 -08005415 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "objc_class_prefix", 36, &msgs[11], NULL, 24, 13, {0},&reftables[172], &reftables[173]),
5416 UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "oneof_decl", 8, &msgs[0], (const upb_def*)(&msgs[15]), 28, 6, {0},&reftables[174], &reftables[175]),
5417 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "oneof_index", 9, &msgs[7], NULL, 19, 8, {0},&reftables[176], &reftables[177]),
5418 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, false, "optimize_for", 9, &msgs[11], (const upb_def*)(&enums[4]), 12, 3, {0},&reftables[178], &reftables[179]),
Josh Haberman94e54b32016-04-14 12:06:09 -07005419 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 7, &msgs[0], (const upb_def*)(&msgs[12]), 25, 5, {0},&reftables[180], &reftables[181]),
5420 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 8, &msgs[9], (const upb_def*)(&msgs[11]), 20, 4, {0},&reftables[182], &reftables[183]),
5421 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 4, &msgs[13], (const upb_def*)(&msgs[14]), 3, 0, {0},&reftables[184], &reftables[185]),
5422 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 8, &msgs[7], (const upb_def*)(&msgs[8]), 3, 0, {0},&reftables[186], &reftables[187]),
5423 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 3, &msgs[16], (const upb_def*)(&msgs[17]), 7, 1, {0},&reftables[188], &reftables[189]),
5424 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 3, &msgs[5], (const upb_def*)(&msgs[6]), 3, 0, {0},&reftables[190], &reftables[191]),
5425 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 3, &msgs[3], (const upb_def*)(&msgs[4]), 7, 1, {0},&reftables[192], &reftables[193]),
Josh Haberman78da6662016-01-13 19:05:43 -08005426 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "output_type", 3, &msgs[13], NULL, 10, 3, {0},&reftables[194], &reftables[195]),
5427 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "package", 2, &msgs[9], NULL, 25, 7, {0},&reftables[196], &reftables[197]),
5428 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "packed", 2, &msgs[8], NULL, 7, 2, {0},&reftables[198], &reftables[199]),
5429 UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, true, "path", 1, &msgs[19], NULL, 4, 0, {0},&reftables[200], &reftables[201]),
5430 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_UINT64, UPB_INTFMT_VARIABLE, false, false, false, false, "positive_int_value", 4, &msgs[20], NULL, 9, 2, {0},&reftables[202], &reftables[203]),
5431 UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "public_dependency", 10, &msgs[9], NULL, 35, 9, {0},&reftables[204], &reftables[205]),
5432 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "py_generic_services", 18, &msgs[11], NULL, 19, 8, {0},&reftables[206], &reftables[207]),
5433 UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_STRING, 0, false, false, false, false, "reserved_name", 10, &msgs[0], NULL, 37, 9, {0},&reftables[208], &reftables[209]),
5434 UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "reserved_range", 9, &msgs[0], (const upb_def*)(&msgs[2]), 31, 7, {0},&reftables[210], &reftables[211]),
5435 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "server_streaming", 6, &msgs[13], NULL, 14, 5, {0},&reftables[212], &reftables[213]),
5436 UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "service", 6, &msgs[9], (const upb_def*)(&msgs[16]), 16, 2, {0},&reftables[214], &reftables[215]),
5437 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "source_code_info", 9, &msgs[9], (const upb_def*)(&msgs[18]), 21, 5, {0},&reftables[216], &reftables[217]),
5438 UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, true, "span", 2, &msgs[19], NULL, 7, 1, {0},&reftables[218], &reftables[219]),
Josh Haberman94e54b32016-04-14 12:06:09 -07005439 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "start", 1, &msgs[2], NULL, 2, 0, {0},&reftables[220], &reftables[221]),
5440 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "start", 1, &msgs[1], NULL, 2, 0, {0},&reftables[222], &reftables[223]),
Josh Haberman78da6662016-01-13 19:05:43 -08005441 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BYTES, 0, false, false, false, false, "string_value", 7, &msgs[20], NULL, 12, 5, {0},&reftables[224], &reftables[225]),
5442 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "syntax", 12, &msgs[9], NULL, 39, 11, {0},&reftables[226], &reftables[227]),
5443 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "trailing_comments", 4, &msgs[19], NULL, 11, 3, {0},&reftables[228], &reftables[229]),
5444 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, false, "type", 5, &msgs[7], (const upb_def*)(&enums[1]), 12, 5, {0},&reftables[230], &reftables[231]),
5445 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "type_name", 6, &msgs[7], NULL, 13, 6, {0},&reftables[232], &reftables[233]),
Josh Haberman94e54b32016-04-14 12:06:09 -07005446 UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[11], (const upb_def*)(&msgs[20]), 5, 0, {0},&reftables[234], &reftables[235]),
Josh Haberman78da6662016-01-13 19:05:43 -08005447 UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[12], (const upb_def*)(&msgs[20]), 5, 0, {0},&reftables[236], &reftables[237]),
Josh Haberman94e54b32016-04-14 12:06:09 -07005448 UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[6], (const upb_def*)(&msgs[20]), 5, 0, {0},&reftables[238], &reftables[239]),
5449 UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[4], (const upb_def*)(&msgs[20]), 5, 0, {0},&reftables[240], &reftables[241]),
5450 UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[8], (const upb_def*)(&msgs[20]), 5, 0, {0},&reftables[242], &reftables[243]),
5451 UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[14], (const upb_def*)(&msgs[20]), 5, 0, {0},&reftables[244], &reftables[245]),
5452 UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[17], (const upb_def*)(&msgs[20]), 5, 0, {0},&reftables[246], &reftables[247]),
Josh Haberman78da6662016-01-13 19:05:43 -08005453 UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "value", 2, &msgs[3], (const upb_def*)(&msgs[5]), 6, 0, {0},&reftables[248], &reftables[249]),
5454 UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "weak", 10, &msgs[8], NULL, 11, 6, {0},&reftables[250], &reftables[251]),
5455 UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "weak_dependency", 11, &msgs[9], NULL, 38, 10, {0},&reftables[252], &reftables[253]),
Chris Fallin91473dc2014-12-12 15:58:26 -08005456};
5457
Josh Haberman78da6662016-01-13 19:05:43 -08005458static const upb_enumdef enums[5] = {
Josh Habermanf654d492016-02-18 11:07:51 -08005459 UPB_ENUMDEF_INIT("google.protobuf.FieldDescriptorProto.Label", UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_INT32, 2, &strentries[188]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &arrays[151], 4, 3), 0, &reftables[254], &reftables[255]),
5460 UPB_ENUMDEF_INIT("google.protobuf.FieldDescriptorProto.Type", UPB_STRTABLE_INIT(18, 31, UPB_CTYPE_INT32, 5, &strentries[192]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &arrays[155], 19, 18), 0, &reftables[256], &reftables[257]),
5461 UPB_ENUMDEF_INIT("google.protobuf.FieldOptions.CType", UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_INT32, 2, &strentries[224]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &arrays[174], 3, 3), 0, &reftables[258], &reftables[259]),
5462 UPB_ENUMDEF_INIT("google.protobuf.FieldOptions.JSType", UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_INT32, 2, &strentries[228]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &arrays[177], 3, 3), 0, &reftables[260], &reftables[261]),
5463 UPB_ENUMDEF_INIT("google.protobuf.FileOptions.OptimizeMode", UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_INT32, 2, &strentries[232]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &arrays[180], 4, 3), 0, &reftables[262], &reftables[263]),
Chris Fallin91473dc2014-12-12 15:58:26 -08005464};
5465
Josh Haberman94e54b32016-04-14 12:06:09 -07005466static const upb_tabent strentries[236] = {
Josh Haberman78da6662016-01-13 19:05:43 -08005467 {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "extension"), UPB_TABVALUE_PTR_INIT(&fields[22]), NULL},
Josh Habermane8ed0212015-06-08 17:56:03 -07005468 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
Josh Haberman78da6662016-01-13 19:05:43 -08005469 {UPB_TABKEY_STR("\015", "\000", "\000", "\000", "reserved_name"), UPB_TABVALUE_PTR_INIT(&fields[82]), NULL},
5470 {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[52]), NULL},
Josh Habermane8ed0212015-06-08 17:56:03 -07005471 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5472 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5473 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
Josh Haberman78da6662016-01-13 19:05:43 -08005474 {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "field"), UPB_TABVALUE_PTR_INIT(&fields[25]), &strentries[12]},
5475 {UPB_TABKEY_STR("\017", "\000", "\000", "\000", "extension_range"), UPB_TABVALUE_PTR_INIT(&fields[24]), &strentries[14]},
Josh Habermane8ed0212015-06-08 17:56:03 -07005476 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
Josh Haberman78da6662016-01-13 19:05:43 -08005477 {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "nested_type"), UPB_TABVALUE_PTR_INIT(&fields[60]), NULL},
5478 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5479 {UPB_TABKEY_STR("\016", "\000", "\000", "\000", "reserved_range"), UPB_TABVALUE_PTR_INIT(&fields[83]), NULL},
Josh Haberman94e54b32016-04-14 12:06:09 -07005480 {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[68]), NULL},
Josh Haberman78da6662016-01-13 19:05:43 -08005481 {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "oneof_decl"), UPB_TABVALUE_PTR_INIT(&fields[65]), NULL},
Josh Haberman94e54b32016-04-14 12:06:09 -07005482 {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "enum_type"), UPB_TABVALUE_PTR_INIT(&fields[19]), &strentries[13]},
5483 {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "start"), UPB_TABVALUE_PTR_INIT(&fields[89]), NULL},
Josh Haberman78da6662016-01-13 19:05:43 -08005484 {UPB_TABKEY_STR("\003", "\000", "\000", "\000", "end"), UPB_TABVALUE_PTR_INIT(&fields[18]), NULL},
5485 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5486 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
Josh Haberman94e54b32016-04-14 12:06:09 -07005487 {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "start"), UPB_TABVALUE_PTR_INIT(&fields[88]), NULL},
Josh Haberman78da6662016-01-13 19:05:43 -08005488 {UPB_TABKEY_STR("\003", "\000", "\000", "\000", "end"), UPB_TABVALUE_PTR_INIT(&fields[17]), NULL},
Josh Habermane8ed0212015-06-08 17:56:03 -07005489 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5490 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5491 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
Josh Haberman78da6662016-01-13 19:05:43 -08005492 {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "value"), UPB_TABVALUE_PTR_INIT(&fields[102]), NULL},
Josh Haberman94e54b32016-04-14 12:06:09 -07005493 {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[74]), NULL},
5494 {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[49]), &strentries[26]},
5495 {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[98]), NULL},
5496 {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[13]), NULL},
Josh Habermane8ed0212015-06-08 17:56:03 -07005497 {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "allow_alias"), UPB_TABVALUE_PTR_INIT(&fields[1]), NULL},
5498 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
Josh Haberman94e54b32016-04-14 12:06:09 -07005499 {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "number"), UPB_TABVALUE_PTR_INIT(&fields[62]), NULL},
Josh Habermane8ed0212015-06-08 17:56:03 -07005500 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
Josh Haberman94e54b32016-04-14 12:06:09 -07005501 {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[73]), NULL},
5502 {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[53]), &strentries[34]},
5503 {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[97]), NULL},
5504 {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[15]), NULL},
Josh Haberman78da6662016-01-13 19:05:43 -08005505 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5506 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5507 {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "oneof_index"), UPB_TABVALUE_PTR_INIT(&fields[66]), NULL},
5508 {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "label"), UPB_TABVALUE_PTR_INIT(&fields[40]), NULL},
5509 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
Josh Haberman94e54b32016-04-14 12:06:09 -07005510 {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[55]), NULL},
Josh Habermane8ed0212015-06-08 17:56:03 -07005511 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5512 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5513 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5514 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
Josh Haberman94e54b32016-04-14 12:06:09 -07005515 {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "number"), UPB_TABVALUE_PTR_INIT(&fields[63]), &strentries[53]},
Josh Habermane8ed0212015-06-08 17:56:03 -07005516 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
Josh Haberman78da6662016-01-13 19:05:43 -08005517 {UPB_TABKEY_STR("\010", "\000", "\000", "\000", "extendee"), UPB_TABVALUE_PTR_INIT(&fields[21]), NULL},
5518 {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "type_name"), UPB_TABVALUE_PTR_INIT(&fields[94]), NULL},
5519 {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "json_name"), UPB_TABVALUE_PTR_INIT(&fields[38]), NULL},
5520 {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "type"), UPB_TABVALUE_PTR_INIT(&fields[93]), &strentries[50]},
5521 {UPB_TABKEY_STR("\015", "\000", "\000", "\000", "default_value"), UPB_TABVALUE_PTR_INIT(&fields[7]), NULL},
Josh Haberman94e54b32016-04-14 12:06:09 -07005522 {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[71]), NULL},
5523 {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[99]), NULL},
Josh Haberman78da6662016-01-13 19:05:43 -08005524 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5525 {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "weak"), UPB_TABVALUE_PTR_INIT(&fields[103]), NULL},
Josh Habermane8ed0212015-06-08 17:56:03 -07005526 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5527 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5528 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5529 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
Josh Haberman78da6662016-01-13 19:05:43 -08005530 {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "packed"), UPB_TABVALUE_PTR_INIT(&fields[77]), NULL},
5531 {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "lazy"), UPB_TABVALUE_PTR_INIT(&fields[41]), NULL},
5532 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5533 {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "ctype"), UPB_TABVALUE_PTR_INIT(&fields[6]), NULL},
5534 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5535 {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "jstype"), UPB_TABVALUE_PTR_INIT(&fields[39]), NULL},
Josh Haberman94e54b32016-04-14 12:06:09 -07005536 {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[10]), NULL},
Josh Habermane8ed0212015-06-08 17:56:03 -07005537 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5538 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
Josh Haberman78da6662016-01-13 19:05:43 -08005539 {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "extension"), UPB_TABVALUE_PTR_INIT(&fields[23]), NULL},
5540 {UPB_TABKEY_STR("\017", "\000", "\000", "\000", "weak_dependency"), UPB_TABVALUE_PTR_INIT(&fields[104]), NULL},
Josh Habermane8ed0212015-06-08 17:56:03 -07005541 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
Josh Haberman94e54b32016-04-14 12:06:09 -07005542 {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[54]), NULL},
Josh Haberman78da6662016-01-13 19:05:43 -08005543 {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "service"), UPB_TABVALUE_PTR_INIT(&fields[85]), NULL},
5544 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5545 {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "source_code_info"), UPB_TABVALUE_PTR_INIT(&fields[86]), NULL},
5546 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5547 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5548 {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "syntax"), UPB_TABVALUE_PTR_INIT(&fields[91]), NULL},
5549 {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "dependency"), UPB_TABVALUE_PTR_INIT(&fields[8]), NULL},
5550 {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "message_type"), UPB_TABVALUE_PTR_INIT(&fields[47]), NULL},
5551 {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "package"), UPB_TABVALUE_PTR_INIT(&fields[76]), NULL},
Josh Haberman94e54b32016-04-14 12:06:09 -07005552 {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[69]), &strentries[86]},
5553 {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "enum_type"), UPB_TABVALUE_PTR_INIT(&fields[20]), NULL},
Josh Haberman78da6662016-01-13 19:05:43 -08005554 {UPB_TABKEY_STR("\021", "\000", "\000", "\000", "public_dependency"), UPB_TABVALUE_PTR_INIT(&fields[80]), &strentries[85]},
5555 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5556 {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "file"), UPB_TABVALUE_PTR_INIT(&fields[26]), NULL},
Josh Habermane8ed0212015-06-08 17:56:03 -07005557 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5558 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5559 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5560 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
Josh Haberman78da6662016-01-13 19:05:43 -08005561 {UPB_TABKEY_STR("\023", "\000", "\000", "\000", "cc_generic_services"), UPB_TABVALUE_PTR_INIT(&fields[3]), NULL},
5562 {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "csharp_namespace"), UPB_TABVALUE_PTR_INIT(&fields[5]), NULL},
Josh Habermane8ed0212015-06-08 17:56:03 -07005563 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5564 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5565 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5566 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5567 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
Josh Haberman78da6662016-01-13 19:05:43 -08005568 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5569 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5570 {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "go_package"), UPB_TABVALUE_PTR_INIT(&fields[27]), NULL},
5571 {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "java_package"), UPB_TABVALUE_PTR_INIT(&fields[35]), &strentries[120]},
5572 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5573 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5574 {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "java_outer_classname"), UPB_TABVALUE_PTR_INIT(&fields[34]), NULL},
Josh Haberman94e54b32016-04-14 12:06:09 -07005575 {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[95]), NULL},
Josh Haberman78da6662016-01-13 19:05:43 -08005576 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5577 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5578 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5579 {UPB_TABKEY_STR("\023", "\000", "\000", "\000", "java_multiple_files"), UPB_TABVALUE_PTR_INIT(&fields[33]), &strentries[117]},
5580 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5581 {UPB_TABKEY_STR("\025", "\000", "\000", "\000", "java_generic_services"), UPB_TABVALUE_PTR_INIT(&fields[32]), &strentries[118]},
5582 {UPB_TABKEY_STR("\035", "\000", "\000", "\000", "java_generate_equals_and_hash"), UPB_TABVALUE_PTR_INIT(&fields[31]), NULL},
5583 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5584 {UPB_TABKEY_STR("\037", "\000", "\000", "\000", "javanano_use_deprecated_package"), UPB_TABVALUE_PTR_INIT(&fields[37]), &strentries[123]},
5585 {UPB_TABKEY_STR("\023", "\000", "\000", "\000", "py_generic_services"), UPB_TABVALUE_PTR_INIT(&fields[81]), NULL},
5586 {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "optimize_for"), UPB_TABVALUE_PTR_INIT(&fields[67]), NULL},
5587 {UPB_TABKEY_STR("\026", "\000", "\000", "\000", "java_string_check_utf8"), UPB_TABVALUE_PTR_INIT(&fields[36]), NULL},
Josh Haberman94e54b32016-04-14 12:06:09 -07005588 {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[12]), &strentries[119]},
Josh Haberman78da6662016-01-13 19:05:43 -08005589 {UPB_TABKEY_STR("\021", "\000", "\000", "\000", "objc_class_prefix"), UPB_TABVALUE_PTR_INIT(&fields[64]), NULL},
5590 {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "cc_enable_arenas"), UPB_TABVALUE_PTR_INIT(&fields[2]), NULL},
5591 {UPB_TABKEY_STR("\027", "\000", "\000", "\000", "message_set_wire_format"), UPB_TABVALUE_PTR_INIT(&fields[46]), &strentries[128]},
5592 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5593 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5594 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5595 {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[96]), NULL},
Josh Haberman94e54b32016-04-14 12:06:09 -07005596 {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[9]), NULL},
Josh Haberman78da6662016-01-13 19:05:43 -08005597 {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "map_entry"), UPB_TABVALUE_PTR_INIT(&fields[45]), NULL},
5598 {UPB_TABKEY_STR("\037", "\000", "\000", "\000", "no_standard_descriptor_accessor"), UPB_TABVALUE_PTR_INIT(&fields[61]), NULL},
5599 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5600 {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "client_streaming"), UPB_TABVALUE_PTR_INIT(&fields[4]), NULL},
5601 {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "server_streaming"), UPB_TABVALUE_PTR_INIT(&fields[84]), NULL},
Josh Haberman94e54b32016-04-14 12:06:09 -07005602 {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[56]), NULL},
Josh Haberman78da6662016-01-13 19:05:43 -08005603 {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "input_type"), UPB_TABVALUE_PTR_INIT(&fields[29]), NULL},
5604 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5605 {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "output_type"), UPB_TABVALUE_PTR_INIT(&fields[75]), NULL},
Josh Haberman94e54b32016-04-14 12:06:09 -07005606 {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[70]), NULL},
5607 {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[100]), NULL},
Josh Haberman78da6662016-01-13 19:05:43 -08005608 {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[11]), NULL},
Josh Habermane8ed0212015-06-08 17:56:03 -07005609 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5610 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5611 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
Josh Haberman78da6662016-01-13 19:05:43 -08005612 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
Josh Haberman94e54b32016-04-14 12:06:09 -07005613 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5614 {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[50]), NULL},
5615 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5616 {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[72]), &strentries[150]},
5617 {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "method"), UPB_TABVALUE_PTR_INIT(&fields[48]), NULL},
5618 {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[57]), &strentries[149]},
5619 {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[101]), NULL},
5620 {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[14]), NULL},
5621 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5622 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5623 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5624 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
Josh Haberman78da6662016-01-13 19:05:43 -08005625 {UPB_TABKEY_STR("\010", "\000", "\000", "\000", "location"), UPB_TABVALUE_PTR_INIT(&fields[44]), NULL},
5626 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5627 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5628 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5629 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5630 {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "span"), UPB_TABVALUE_PTR_INIT(&fields[87]), &strentries[167]},
5631 {UPB_TABKEY_STR("\031", "\000", "\000", "\000", "leading_detached_comments"), UPB_TABVALUE_PTR_INIT(&fields[43]), &strentries[165]},
5632 {UPB_TABKEY_STR("\021", "\000", "\000", "\000", "trailing_comments"), UPB_TABVALUE_PTR_INIT(&fields[92]), NULL},
5633 {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "leading_comments"), UPB_TABVALUE_PTR_INIT(&fields[42]), &strentries[164]},
5634 {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "path"), UPB_TABVALUE_PTR_INIT(&fields[78]), NULL},
5635 {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "double_value"), UPB_TABVALUE_PTR_INIT(&fields[16]), NULL},
5636 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5637 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
Josh Haberman94e54b32016-04-14 12:06:09 -07005638 {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[51]), NULL},
Josh Haberman78da6662016-01-13 19:05:43 -08005639 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5640 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5641 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5642 {UPB_TABKEY_STR("\022", "\000", "\000", "\000", "negative_int_value"), UPB_TABVALUE_PTR_INIT(&fields[59]), NULL},
Josh Habermane8ed0212015-06-08 17:56:03 -07005643 {UPB_TABKEY_STR("\017", "\000", "\000", "\000", "aggregate_value"), UPB_TABVALUE_PTR_INIT(&fields[0]), NULL},
5644 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5645 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5646 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5647 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
Josh Haberman78da6662016-01-13 19:05:43 -08005648 {UPB_TABKEY_STR("\022", "\000", "\000", "\000", "positive_int_value"), UPB_TABVALUE_PTR_INIT(&fields[79]), NULL},
5649 {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "identifier_value"), UPB_TABVALUE_PTR_INIT(&fields[28]), NULL},
5650 {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "string_value"), UPB_TABVALUE_PTR_INIT(&fields[90]), &strentries[182]},
Josh Habermane8ed0212015-06-08 17:56:03 -07005651 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5652 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
Josh Haberman78da6662016-01-13 19:05:43 -08005653 {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "is_extension"), UPB_TABVALUE_PTR_INIT(&fields[30]), NULL},
5654 {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "name_part"), UPB_TABVALUE_PTR_INIT(&fields[58]), NULL},
5655 {UPB_TABKEY_STR("\016", "\000", "\000", "\000", "LABEL_REQUIRED"), UPB_TABVALUE_INT_INIT(2), &strentries[190]},
Josh Habermane8ed0212015-06-08 17:56:03 -07005656 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5657 {UPB_TABKEY_STR("\016", "\000", "\000", "\000", "LABEL_REPEATED"), UPB_TABVALUE_INT_INIT(3), NULL},
5658 {UPB_TABKEY_STR("\016", "\000", "\000", "\000", "LABEL_OPTIONAL"), UPB_TABVALUE_INT_INIT(1), NULL},
5659 {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "TYPE_FIXED64"), UPB_TABVALUE_INT_INIT(6), NULL},
5660 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5661 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5662 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5663 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5664 {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "TYPE_STRING"), UPB_TABVALUE_INT_INIT(9), NULL},
Josh Haberman78da6662016-01-13 19:05:43 -08005665 {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "TYPE_FLOAT"), UPB_TABVALUE_INT_INIT(2), &strentries[221]},
Josh Habermane8ed0212015-06-08 17:56:03 -07005666 {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "TYPE_DOUBLE"), UPB_TABVALUE_INT_INIT(1), NULL},
5667 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5668 {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "TYPE_INT32"), UPB_TABVALUE_INT_INIT(5), NULL},
5669 {UPB_TABKEY_STR("\015", "\000", "\000", "\000", "TYPE_SFIXED32"), UPB_TABVALUE_INT_INIT(15), NULL},
5670 {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "TYPE_FIXED32"), UPB_TABVALUE_INT_INIT(7), NULL},
5671 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
Josh Haberman78da6662016-01-13 19:05:43 -08005672 {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "TYPE_MESSAGE"), UPB_TABVALUE_INT_INIT(11), &strentries[222]},
Josh Habermane8ed0212015-06-08 17:56:03 -07005673 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5674 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
Josh Haberman78da6662016-01-13 19:05:43 -08005675 {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "TYPE_INT64"), UPB_TABVALUE_INT_INIT(3), &strentries[219]},
Josh Habermane8ed0212015-06-08 17:56:03 -07005676 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5677 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5678 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5679 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5680 {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "TYPE_ENUM"), UPB_TABVALUE_INT_INIT(14), NULL},
5681 {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "TYPE_UINT32"), UPB_TABVALUE_INT_INIT(13), NULL},
5682 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
Josh Haberman78da6662016-01-13 19:05:43 -08005683 {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "TYPE_UINT64"), UPB_TABVALUE_INT_INIT(4), &strentries[218]},
Josh Habermane8ed0212015-06-08 17:56:03 -07005684 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5685 {UPB_TABKEY_STR("\015", "\000", "\000", "\000", "TYPE_SFIXED64"), UPB_TABVALUE_INT_INIT(16), NULL},
5686 {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "TYPE_BYTES"), UPB_TABVALUE_INT_INIT(12), NULL},
5687 {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "TYPE_SINT64"), UPB_TABVALUE_INT_INIT(18), NULL},
5688 {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "TYPE_BOOL"), UPB_TABVALUE_INT_INIT(8), NULL},
5689 {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "TYPE_GROUP"), UPB_TABVALUE_INT_INIT(10), NULL},
5690 {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "TYPE_SINT32"), UPB_TABVALUE_INT_INIT(17), NULL},
5691 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5692 {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "CORD"), UPB_TABVALUE_INT_INIT(1), NULL},
Josh Haberman78da6662016-01-13 19:05:43 -08005693 {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "STRING"), UPB_TABVALUE_INT_INIT(0), &strentries[225]},
Josh Habermane8ed0212015-06-08 17:56:03 -07005694 {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "STRING_PIECE"), UPB_TABVALUE_INT_INIT(2), NULL},
Josh Haberman78da6662016-01-13 19:05:43 -08005695 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5696 {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "JS_NORMAL"), UPB_TABVALUE_INT_INIT(0), NULL},
5697 {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "JS_NUMBER"), UPB_TABVALUE_INT_INIT(2), NULL},
5698 {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "JS_STRING"), UPB_TABVALUE_INT_INIT(1), NULL},
Josh Habermane8ed0212015-06-08 17:56:03 -07005699 {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "CODE_SIZE"), UPB_TABVALUE_INT_INIT(2), NULL},
Josh Haberman78da6662016-01-13 19:05:43 -08005700 {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "SPEED"), UPB_TABVALUE_INT_INIT(1), &strentries[235]},
Josh Habermane8ed0212015-06-08 17:56:03 -07005701 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5702 {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "LITE_RUNTIME"), UPB_TABVALUE_INT_INIT(3), NULL},
Chris Fallin91473dc2014-12-12 15:58:26 -08005703};
5704
Josh Haberman78da6662016-01-13 19:05:43 -08005705static const upb_tabent intentries[18] = {
Josh Habermane8ed0212015-06-08 17:56:03 -07005706 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
Josh Haberman94e54b32016-04-14 12:06:09 -07005707 {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[98]), NULL},
Josh Habermane8ed0212015-06-08 17:56:03 -07005708 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
Josh Haberman78da6662016-01-13 19:05:43 -08005709 {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[97]), NULL},
Josh Habermane8ed0212015-06-08 17:56:03 -07005710 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
Josh Haberman78da6662016-01-13 19:05:43 -08005711 {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[99]), NULL},
Josh Habermane8ed0212015-06-08 17:56:03 -07005712 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
Josh Haberman94e54b32016-04-14 12:06:09 -07005713 {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[95]), NULL},
5714 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
Josh Haberman78da6662016-01-13 19:05:43 -08005715 {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[96]), NULL},
Josh Habermane8ed0212015-06-08 17:56:03 -07005716 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
Josh Haberman78da6662016-01-13 19:05:43 -08005717 {UPB_TABKEY_NUM(33), UPB_TABVALUE_PTR_INIT(&fields[11]), NULL},
5718 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
Josh Haberman94e54b32016-04-14 12:06:09 -07005719 {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[100]), NULL},
5720 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5721 {UPB_TABKEY_NUM(33), UPB_TABVALUE_PTR_INIT(&fields[14]), NULL},
5722 {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5723 {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[101]), NULL},
Chris Fallin91473dc2014-12-12 15:58:26 -08005724};
5725
Josh Habermanf654d492016-02-18 11:07:51 -08005726static const upb_tabval arrays[184] = {
Josh Habermane8ed0212015-06-08 17:56:03 -07005727 UPB_TABVALUE_EMPTY_INIT,
Josh Haberman78da6662016-01-13 19:05:43 -08005728 UPB_TABVALUE_PTR_INIT(&fields[52]),
5729 UPB_TABVALUE_PTR_INIT(&fields[25]),
5730 UPB_TABVALUE_PTR_INIT(&fields[60]),
Josh Haberman94e54b32016-04-14 12:06:09 -07005731 UPB_TABVALUE_PTR_INIT(&fields[19]),
Josh Haberman78da6662016-01-13 19:05:43 -08005732 UPB_TABVALUE_PTR_INIT(&fields[24]),
5733 UPB_TABVALUE_PTR_INIT(&fields[22]),
Josh Haberman94e54b32016-04-14 12:06:09 -07005734 UPB_TABVALUE_PTR_INIT(&fields[68]),
Josh Haberman78da6662016-01-13 19:05:43 -08005735 UPB_TABVALUE_PTR_INIT(&fields[65]),
5736 UPB_TABVALUE_PTR_INIT(&fields[83]),
5737 UPB_TABVALUE_PTR_INIT(&fields[82]),
Josh Habermane8ed0212015-06-08 17:56:03 -07005738 UPB_TABVALUE_EMPTY_INIT,
Josh Haberman94e54b32016-04-14 12:06:09 -07005739 UPB_TABVALUE_PTR_INIT(&fields[89]),
Josh Haberman78da6662016-01-13 19:05:43 -08005740 UPB_TABVALUE_PTR_INIT(&fields[18]),
Josh Habermane8ed0212015-06-08 17:56:03 -07005741 UPB_TABVALUE_EMPTY_INIT,
Josh Haberman94e54b32016-04-14 12:06:09 -07005742 UPB_TABVALUE_PTR_INIT(&fields[88]),
Josh Haberman78da6662016-01-13 19:05:43 -08005743 UPB_TABVALUE_PTR_INIT(&fields[17]),
5744 UPB_TABVALUE_EMPTY_INIT,
Josh Haberman94e54b32016-04-14 12:06:09 -07005745 UPB_TABVALUE_PTR_INIT(&fields[49]),
Josh Haberman78da6662016-01-13 19:05:43 -08005746 UPB_TABVALUE_PTR_INIT(&fields[102]),
Josh Haberman94e54b32016-04-14 12:06:09 -07005747 UPB_TABVALUE_PTR_INIT(&fields[74]),
Josh Habermane8ed0212015-06-08 17:56:03 -07005748 UPB_TABVALUE_EMPTY_INIT,
5749 UPB_TABVALUE_EMPTY_INIT,
5750 UPB_TABVALUE_PTR_INIT(&fields[1]),
Josh Haberman94e54b32016-04-14 12:06:09 -07005751 UPB_TABVALUE_PTR_INIT(&fields[13]),
Josh Habermane8ed0212015-06-08 17:56:03 -07005752 UPB_TABVALUE_EMPTY_INIT,
Josh Haberman94e54b32016-04-14 12:06:09 -07005753 UPB_TABVALUE_PTR_INIT(&fields[53]),
Josh Haberman78da6662016-01-13 19:05:43 -08005754 UPB_TABVALUE_PTR_INIT(&fields[62]),
Josh Haberman94e54b32016-04-14 12:06:09 -07005755 UPB_TABVALUE_PTR_INIT(&fields[73]),
5756 UPB_TABVALUE_EMPTY_INIT,
5757 UPB_TABVALUE_PTR_INIT(&fields[15]),
5758 UPB_TABVALUE_EMPTY_INIT,
5759 UPB_TABVALUE_PTR_INIT(&fields[55]),
5760 UPB_TABVALUE_PTR_INIT(&fields[21]),
5761 UPB_TABVALUE_PTR_INIT(&fields[63]),
Josh Haberman78da6662016-01-13 19:05:43 -08005762 UPB_TABVALUE_PTR_INIT(&fields[40]),
5763 UPB_TABVALUE_PTR_INIT(&fields[93]),
5764 UPB_TABVALUE_PTR_INIT(&fields[94]),
5765 UPB_TABVALUE_PTR_INIT(&fields[7]),
Josh Haberman94e54b32016-04-14 12:06:09 -07005766 UPB_TABVALUE_PTR_INIT(&fields[71]),
Josh Haberman78da6662016-01-13 19:05:43 -08005767 UPB_TABVALUE_PTR_INIT(&fields[66]),
5768 UPB_TABVALUE_PTR_INIT(&fields[38]),
5769 UPB_TABVALUE_EMPTY_INIT,
5770 UPB_TABVALUE_PTR_INIT(&fields[6]),
5771 UPB_TABVALUE_PTR_INIT(&fields[77]),
Josh Haberman94e54b32016-04-14 12:06:09 -07005772 UPB_TABVALUE_PTR_INIT(&fields[10]),
Josh Haberman78da6662016-01-13 19:05:43 -08005773 UPB_TABVALUE_EMPTY_INIT,
Josh Habermane8ed0212015-06-08 17:56:03 -07005774 UPB_TABVALUE_PTR_INIT(&fields[41]),
Josh Haberman78da6662016-01-13 19:05:43 -08005775 UPB_TABVALUE_PTR_INIT(&fields[39]),
Josh Habermane8ed0212015-06-08 17:56:03 -07005776 UPB_TABVALUE_EMPTY_INIT,
5777 UPB_TABVALUE_EMPTY_INIT,
5778 UPB_TABVALUE_EMPTY_INIT,
Josh Haberman78da6662016-01-13 19:05:43 -08005779 UPB_TABVALUE_PTR_INIT(&fields[103]),
Josh Habermane8ed0212015-06-08 17:56:03 -07005780 UPB_TABVALUE_EMPTY_INIT,
Josh Haberman94e54b32016-04-14 12:06:09 -07005781 UPB_TABVALUE_PTR_INIT(&fields[54]),
Josh Haberman78da6662016-01-13 19:05:43 -08005782 UPB_TABVALUE_PTR_INIT(&fields[76]),
5783 UPB_TABVALUE_PTR_INIT(&fields[8]),
5784 UPB_TABVALUE_PTR_INIT(&fields[47]),
Josh Haberman94e54b32016-04-14 12:06:09 -07005785 UPB_TABVALUE_PTR_INIT(&fields[20]),
Josh Haberman78da6662016-01-13 19:05:43 -08005786 UPB_TABVALUE_PTR_INIT(&fields[85]),
5787 UPB_TABVALUE_PTR_INIT(&fields[23]),
Josh Haberman94e54b32016-04-14 12:06:09 -07005788 UPB_TABVALUE_PTR_INIT(&fields[69]),
Josh Haberman78da6662016-01-13 19:05:43 -08005789 UPB_TABVALUE_PTR_INIT(&fields[86]),
5790 UPB_TABVALUE_PTR_INIT(&fields[80]),
5791 UPB_TABVALUE_PTR_INIT(&fields[104]),
5792 UPB_TABVALUE_PTR_INIT(&fields[91]),
5793 UPB_TABVALUE_EMPTY_INIT,
5794 UPB_TABVALUE_PTR_INIT(&fields[26]),
5795 UPB_TABVALUE_EMPTY_INIT,
5796 UPB_TABVALUE_PTR_INIT(&fields[35]),
5797 UPB_TABVALUE_EMPTY_INIT,
5798 UPB_TABVALUE_EMPTY_INIT,
5799 UPB_TABVALUE_EMPTY_INIT,
5800 UPB_TABVALUE_EMPTY_INIT,
5801 UPB_TABVALUE_EMPTY_INIT,
5802 UPB_TABVALUE_EMPTY_INIT,
Josh Habermane8ed0212015-06-08 17:56:03 -07005803 UPB_TABVALUE_PTR_INIT(&fields[34]),
Josh Haberman78da6662016-01-13 19:05:43 -08005804 UPB_TABVALUE_PTR_INIT(&fields[67]),
5805 UPB_TABVALUE_PTR_INIT(&fields[33]),
5806 UPB_TABVALUE_PTR_INIT(&fields[27]),
5807 UPB_TABVALUE_EMPTY_INIT,
5808 UPB_TABVALUE_EMPTY_INIT,
5809 UPB_TABVALUE_EMPTY_INIT,
5810 UPB_TABVALUE_EMPTY_INIT,
5811 UPB_TABVALUE_PTR_INIT(&fields[3]),
Josh Habermane8ed0212015-06-08 17:56:03 -07005812 UPB_TABVALUE_PTR_INIT(&fields[32]),
Josh Haberman78da6662016-01-13 19:05:43 -08005813 UPB_TABVALUE_PTR_INIT(&fields[81]),
Josh Habermane8ed0212015-06-08 17:56:03 -07005814 UPB_TABVALUE_EMPTY_INIT,
Josh Haberman78da6662016-01-13 19:05:43 -08005815 UPB_TABVALUE_PTR_INIT(&fields[31]),
Josh Habermane8ed0212015-06-08 17:56:03 -07005816 UPB_TABVALUE_EMPTY_INIT,
Josh Haberman78da6662016-01-13 19:05:43 -08005817 UPB_TABVALUE_EMPTY_INIT,
Josh Haberman94e54b32016-04-14 12:06:09 -07005818 UPB_TABVALUE_PTR_INIT(&fields[12]),
Josh Habermane8ed0212015-06-08 17:56:03 -07005819 UPB_TABVALUE_EMPTY_INIT,
5820 UPB_TABVALUE_EMPTY_INIT,
5821 UPB_TABVALUE_EMPTY_INIT,
Josh Haberman78da6662016-01-13 19:05:43 -08005822 UPB_TABVALUE_PTR_INIT(&fields[36]),
Josh Habermane8ed0212015-06-08 17:56:03 -07005823 UPB_TABVALUE_EMPTY_INIT,
5824 UPB_TABVALUE_EMPTY_INIT,
5825 UPB_TABVALUE_EMPTY_INIT,
5826 UPB_TABVALUE_PTR_INIT(&fields[2]),
Josh Habermane8ed0212015-06-08 17:56:03 -07005827 UPB_TABVALUE_EMPTY_INIT,
Josh Haberman78da6662016-01-13 19:05:43 -08005828 UPB_TABVALUE_EMPTY_INIT,
5829 UPB_TABVALUE_EMPTY_INIT,
5830 UPB_TABVALUE_EMPTY_INIT,
5831 UPB_TABVALUE_PTR_INIT(&fields[64]),
5832 UPB_TABVALUE_PTR_INIT(&fields[5]),
5833 UPB_TABVALUE_PTR_INIT(&fields[37]),
Josh Habermane8ed0212015-06-08 17:56:03 -07005834 UPB_TABVALUE_EMPTY_INIT,
Josh Haberman78da6662016-01-13 19:05:43 -08005835 UPB_TABVALUE_PTR_INIT(&fields[46]),
5836 UPB_TABVALUE_PTR_INIT(&fields[61]),
Josh Haberman94e54b32016-04-14 12:06:09 -07005837 UPB_TABVALUE_PTR_INIT(&fields[9]),
Josh Haberman78da6662016-01-13 19:05:43 -08005838 UPB_TABVALUE_EMPTY_INIT,
5839 UPB_TABVALUE_EMPTY_INIT,
5840 UPB_TABVALUE_EMPTY_INIT,
Josh Habermane8ed0212015-06-08 17:56:03 -07005841 UPB_TABVALUE_PTR_INIT(&fields[45]),
5842 UPB_TABVALUE_EMPTY_INIT,
Josh Haberman94e54b32016-04-14 12:06:09 -07005843 UPB_TABVALUE_PTR_INIT(&fields[56]),
Josh Haberman78da6662016-01-13 19:05:43 -08005844 UPB_TABVALUE_PTR_INIT(&fields[29]),
5845 UPB_TABVALUE_PTR_INIT(&fields[75]),
Josh Haberman94e54b32016-04-14 12:06:09 -07005846 UPB_TABVALUE_PTR_INIT(&fields[70]),
Josh Haberman78da6662016-01-13 19:05:43 -08005847 UPB_TABVALUE_PTR_INIT(&fields[4]),
5848 UPB_TABVALUE_PTR_INIT(&fields[84]),
5849 UPB_TABVALUE_EMPTY_INIT,
5850 UPB_TABVALUE_EMPTY_INIT,
Josh Haberman94e54b32016-04-14 12:06:09 -07005851 UPB_TABVALUE_PTR_INIT(&fields[50]),
Josh Habermane8ed0212015-06-08 17:56:03 -07005852 UPB_TABVALUE_EMPTY_INIT,
Josh Haberman94e54b32016-04-14 12:06:09 -07005853 UPB_TABVALUE_PTR_INIT(&fields[57]),
Josh Haberman78da6662016-01-13 19:05:43 -08005854 UPB_TABVALUE_PTR_INIT(&fields[48]),
Josh Haberman94e54b32016-04-14 12:06:09 -07005855 UPB_TABVALUE_PTR_INIT(&fields[72]),
Josh Habermane8ed0212015-06-08 17:56:03 -07005856 UPB_TABVALUE_EMPTY_INIT,
5857 UPB_TABVALUE_EMPTY_INIT,
Josh Haberman78da6662016-01-13 19:05:43 -08005858 UPB_TABVALUE_PTR_INIT(&fields[44]),
Josh Habermane8ed0212015-06-08 17:56:03 -07005859 UPB_TABVALUE_EMPTY_INIT,
Josh Haberman78da6662016-01-13 19:05:43 -08005860 UPB_TABVALUE_PTR_INIT(&fields[78]),
5861 UPB_TABVALUE_PTR_INIT(&fields[87]),
5862 UPB_TABVALUE_PTR_INIT(&fields[42]),
5863 UPB_TABVALUE_PTR_INIT(&fields[92]),
Josh Habermane8ed0212015-06-08 17:56:03 -07005864 UPB_TABVALUE_EMPTY_INIT,
Josh Habermane8ed0212015-06-08 17:56:03 -07005865 UPB_TABVALUE_PTR_INIT(&fields[43]),
Josh Haberman78da6662016-01-13 19:05:43 -08005866 UPB_TABVALUE_EMPTY_INIT,
5867 UPB_TABVALUE_EMPTY_INIT,
Josh Haberman94e54b32016-04-14 12:06:09 -07005868 UPB_TABVALUE_PTR_INIT(&fields[51]),
Josh Haberman78da6662016-01-13 19:05:43 -08005869 UPB_TABVALUE_PTR_INIT(&fields[28]),
5870 UPB_TABVALUE_PTR_INIT(&fields[79]),
5871 UPB_TABVALUE_PTR_INIT(&fields[59]),
5872 UPB_TABVALUE_PTR_INIT(&fields[16]),
5873 UPB_TABVALUE_PTR_INIT(&fields[90]),
Josh Habermane8ed0212015-06-08 17:56:03 -07005874 UPB_TABVALUE_PTR_INIT(&fields[0]),
5875 UPB_TABVALUE_EMPTY_INIT,
Josh Haberman78da6662016-01-13 19:05:43 -08005876 UPB_TABVALUE_PTR_INIT(&fields[58]),
5877 UPB_TABVALUE_PTR_INIT(&fields[30]),
Josh Habermane8ed0212015-06-08 17:56:03 -07005878 UPB_TABVALUE_EMPTY_INIT,
5879 UPB_TABVALUE_PTR_INIT("LABEL_OPTIONAL"),
5880 UPB_TABVALUE_PTR_INIT("LABEL_REQUIRED"),
5881 UPB_TABVALUE_PTR_INIT("LABEL_REPEATED"),
5882 UPB_TABVALUE_EMPTY_INIT,
5883 UPB_TABVALUE_PTR_INIT("TYPE_DOUBLE"),
5884 UPB_TABVALUE_PTR_INIT("TYPE_FLOAT"),
5885 UPB_TABVALUE_PTR_INIT("TYPE_INT64"),
5886 UPB_TABVALUE_PTR_INIT("TYPE_UINT64"),
5887 UPB_TABVALUE_PTR_INIT("TYPE_INT32"),
5888 UPB_TABVALUE_PTR_INIT("TYPE_FIXED64"),
5889 UPB_TABVALUE_PTR_INIT("TYPE_FIXED32"),
5890 UPB_TABVALUE_PTR_INIT("TYPE_BOOL"),
5891 UPB_TABVALUE_PTR_INIT("TYPE_STRING"),
5892 UPB_TABVALUE_PTR_INIT("TYPE_GROUP"),
5893 UPB_TABVALUE_PTR_INIT("TYPE_MESSAGE"),
5894 UPB_TABVALUE_PTR_INIT("TYPE_BYTES"),
5895 UPB_TABVALUE_PTR_INIT("TYPE_UINT32"),
5896 UPB_TABVALUE_PTR_INIT("TYPE_ENUM"),
5897 UPB_TABVALUE_PTR_INIT("TYPE_SFIXED32"),
5898 UPB_TABVALUE_PTR_INIT("TYPE_SFIXED64"),
5899 UPB_TABVALUE_PTR_INIT("TYPE_SINT32"),
5900 UPB_TABVALUE_PTR_INIT("TYPE_SINT64"),
5901 UPB_TABVALUE_PTR_INIT("STRING"),
5902 UPB_TABVALUE_PTR_INIT("CORD"),
5903 UPB_TABVALUE_PTR_INIT("STRING_PIECE"),
Josh Haberman78da6662016-01-13 19:05:43 -08005904 UPB_TABVALUE_PTR_INIT("JS_NORMAL"),
5905 UPB_TABVALUE_PTR_INIT("JS_STRING"),
5906 UPB_TABVALUE_PTR_INIT("JS_NUMBER"),
Josh Habermane8ed0212015-06-08 17:56:03 -07005907 UPB_TABVALUE_EMPTY_INIT,
5908 UPB_TABVALUE_PTR_INIT("SPEED"),
5909 UPB_TABVALUE_PTR_INIT("CODE_SIZE"),
5910 UPB_TABVALUE_PTR_INIT("LITE_RUNTIME"),
Chris Fallin91473dc2014-12-12 15:58:26 -08005911};
5912
Chris Fallin91473dc2014-12-12 15:58:26 -08005913#ifdef UPB_DEBUG_REFS
Josh Haberman94e54b32016-04-14 12:06:09 -07005914static upb_inttable reftables[264] = {
Josh Haberman78da6662016-01-13 19:05:43 -08005915 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5916 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5917 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5918 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5919 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5920 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5921 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5922 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5923 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5924 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5925 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5926 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5927 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5928 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5929 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5930 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5931 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5932 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5933 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5934 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5935 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5936 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5937 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5938 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5939 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5940 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5941 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5942 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5943 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5944 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5945 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5946 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5947 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5948 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5949 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5950 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5951 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5952 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5953 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5954 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5955 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5956 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5957 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5958 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5959 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5960 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5961 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5962 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5963 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5964 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5965 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5966 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
Chris Fallin91473dc2014-12-12 15:58:26 -08005967 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5968 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5969 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5970 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5971 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5972 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5973 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5974 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5975 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5976 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5977 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5978 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5979 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5980 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5981 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5982 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5983 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5984 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5985 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5986 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5987 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5988 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5989 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5990 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5991 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5992 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5993 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5994 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5995 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5996 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5997 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5998 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
5999 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6000 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6001 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6002 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6003 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6004 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6005 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6006 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6007 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6008 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6009 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6010 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6011 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6012 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6013 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6014 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6015 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6016 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6017 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6018 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6019 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6020 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6021 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6022 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6023 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6024 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6025 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6026 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6027 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6028 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6029 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6030 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6031 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6032 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6033 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6034 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6035 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6036 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6037 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6038 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6039 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6040 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6041 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6042 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6043 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6044 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6045 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6046 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6047 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6048 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6049 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6050 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6051 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6052 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6053 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6054 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6055 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6056 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6057 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6058 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6059 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6060 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6061 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6062 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6063 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6064 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6065 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6066 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6067 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6068 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6069 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6070 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6071 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6072 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6073 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6074 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6075 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6076 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6077 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6078 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6079 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6080 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6081 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6082 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6083 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6084 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6085 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6086 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6087 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6088 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6089 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6090 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6091 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6092 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6093 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6094 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6095 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6096 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6097 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6098 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6099 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6100 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6101 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6102 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6103 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6104 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6105 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6106 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6107 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6108 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6109 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6110 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6111 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6112 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6113 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6114 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6115 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6116 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6117 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6118 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6119 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6120 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6121 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6122 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6123 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6124 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6125 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6126 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6127 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6128 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6129 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6130 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6131 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6132 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6133 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6134 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6135 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6136 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6137 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6138 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6139 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6140 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6141 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6142 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6143 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6144 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6145 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6146 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6147 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6148 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6149 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6150 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6151 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6152 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6153 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6154 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6155 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6156 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6157 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6158 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6159 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6160 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6161 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6162 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6163 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6164 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6165 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6166 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6167 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6168 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6169 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6170 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6171 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6172 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6173 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6174 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6175 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6176 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6177 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6178 UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6179};
6180#endif
6181
Josh Haberman94e54b32016-04-14 12:06:09 -07006182static const upb_msgdef *refm(const upb_msgdef *m, const void *owner) {
6183 upb_msgdef_ref(m, owner);
6184 return m;
6185}
6186
6187static const upb_enumdef *refe(const upb_enumdef *e, const void *owner) {
6188 upb_enumdef_ref(e, owner);
6189 return e;
6190}
6191
6192/* Public API. */
6193const upb_msgdef *upbdefs_google_protobuf_DescriptorProto_get(const void *owner) { return refm(&msgs[0], owner); }
6194const upb_msgdef *upbdefs_google_protobuf_DescriptorProto_ExtensionRange_get(const void *owner) { return refm(&msgs[1], owner); }
6195const upb_msgdef *upbdefs_google_protobuf_DescriptorProto_ReservedRange_get(const void *owner) { return refm(&msgs[2], owner); }
6196const upb_msgdef *upbdefs_google_protobuf_EnumDescriptorProto_get(const void *owner) { return refm(&msgs[3], owner); }
6197const upb_msgdef *upbdefs_google_protobuf_EnumOptions_get(const void *owner) { return refm(&msgs[4], owner); }
6198const upb_msgdef *upbdefs_google_protobuf_EnumValueDescriptorProto_get(const void *owner) { return refm(&msgs[5], owner); }
6199const upb_msgdef *upbdefs_google_protobuf_EnumValueOptions_get(const void *owner) { return refm(&msgs[6], owner); }
6200const upb_msgdef *upbdefs_google_protobuf_FieldDescriptorProto_get(const void *owner) { return refm(&msgs[7], owner); }
6201const upb_msgdef *upbdefs_google_protobuf_FieldOptions_get(const void *owner) { return refm(&msgs[8], owner); }
6202const upb_msgdef *upbdefs_google_protobuf_FileDescriptorProto_get(const void *owner) { return refm(&msgs[9], owner); }
6203const upb_msgdef *upbdefs_google_protobuf_FileDescriptorSet_get(const void *owner) { return refm(&msgs[10], owner); }
6204const upb_msgdef *upbdefs_google_protobuf_FileOptions_get(const void *owner) { return refm(&msgs[11], owner); }
6205const upb_msgdef *upbdefs_google_protobuf_MessageOptions_get(const void *owner) { return refm(&msgs[12], owner); }
6206const upb_msgdef *upbdefs_google_protobuf_MethodDescriptorProto_get(const void *owner) { return refm(&msgs[13], owner); }
6207const upb_msgdef *upbdefs_google_protobuf_MethodOptions_get(const void *owner) { return refm(&msgs[14], owner); }
6208const upb_msgdef *upbdefs_google_protobuf_OneofDescriptorProto_get(const void *owner) { return refm(&msgs[15], owner); }
6209const upb_msgdef *upbdefs_google_protobuf_ServiceDescriptorProto_get(const void *owner) { return refm(&msgs[16], owner); }
6210const upb_msgdef *upbdefs_google_protobuf_ServiceOptions_get(const void *owner) { return refm(&msgs[17], owner); }
6211const upb_msgdef *upbdefs_google_protobuf_SourceCodeInfo_get(const void *owner) { return refm(&msgs[18], owner); }
6212const upb_msgdef *upbdefs_google_protobuf_SourceCodeInfo_Location_get(const void *owner) { return refm(&msgs[19], owner); }
6213const upb_msgdef *upbdefs_google_protobuf_UninterpretedOption_get(const void *owner) { return refm(&msgs[20], owner); }
6214const upb_msgdef *upbdefs_google_protobuf_UninterpretedOption_NamePart_get(const void *owner) { return refm(&msgs[21], owner); }
6215
6216const upb_enumdef *upbdefs_google_protobuf_FieldDescriptorProto_Label_get(const void *owner) { return refe(&enums[0], owner); }
6217const upb_enumdef *upbdefs_google_protobuf_FieldDescriptorProto_Type_get(const void *owner) { return refe(&enums[1], owner); }
6218const upb_enumdef *upbdefs_google_protobuf_FieldOptions_CType_get(const void *owner) { return refe(&enums[2], owner); }
6219const upb_enumdef *upbdefs_google_protobuf_FieldOptions_JSType_get(const void *owner) { return refe(&enums[3], owner); }
6220const upb_enumdef *upbdefs_google_protobuf_FileOptions_OptimizeMode_get(const void *owner) { return refe(&enums[4], owner); }
Chris Fallin91473dc2014-12-12 15:58:26 -08006221/*
Josh Haberman181c7f22015-07-15 11:05:10 -07006222** XXX: The routines in this file that consume a string do not currently
6223** support having the string span buffers. In the future, as upb_sink and
6224** its buffering/sharing functionality evolve there should be an easy and
6225** idiomatic way of correctly handling this case. For now, we accept this
6226** limitation since we currently only parse descriptors from single strings.
6227*/
Chris Fallin91473dc2014-12-12 15:58:26 -08006228
6229
6230#include <errno.h>
6231#include <stdlib.h>
6232#include <string.h>
6233
Josh Haberman78da6662016-01-13 19:05:43 -08006234/* Compares a NULL-terminated string with a non-NULL-terminated string. */
6235static bool upb_streq(const char *str, const char *buf, size_t n) {
6236 return strlen(str) == n && memcmp(str, buf, n) == 0;
6237}
6238
Josh Habermane8ed0212015-06-08 17:56:03 -07006239/* We keep a stack of all the messages scopes we are currently in, as well as
6240 * the top-level file scope. This is necessary to correctly qualify the
6241 * definitions that are contained inside. "name" tracks the name of the
6242 * message or package (a bare name -- not qualified by any enclosing scopes). */
Chris Fallind3262772015-05-14 18:24:26 -07006243typedef struct {
6244 char *name;
Josh Habermane8ed0212015-06-08 17:56:03 -07006245 /* Index of the first def that is under this scope. For msgdefs, the
6246 * msgdef itself is at start-1. */
Chris Fallind3262772015-05-14 18:24:26 -07006247 int start;
6248} upb_descreader_frame;
6249
Josh Habermane8ed0212015-06-08 17:56:03 -07006250/* The maximum number of nested declarations that are allowed, ie.
6251 * message Foo {
6252 * message Bar {
6253 * message Baz {
6254 * }
6255 * }
6256 * }
6257 *
6258 * This is a resource limit that affects how big our runtime stack can grow.
6259 * TODO: make this a runtime-settable property of the Reader instance. */
Chris Fallind3262772015-05-14 18:24:26 -07006260#define UPB_MAX_MESSAGE_NESTING 64
6261
6262struct upb_descreader {
6263 upb_sink sink;
Josh Haberman94e54b32016-04-14 12:06:09 -07006264 upb_inttable files;
6265 upb_filedef *file; /* The last file in files. */
Chris Fallind3262772015-05-14 18:24:26 -07006266 upb_descreader_frame stack[UPB_MAX_MESSAGE_NESTING];
6267 int stack_len;
6268
6269 uint32_t number;
6270 char *name;
6271 bool saw_number;
6272 bool saw_name;
6273
6274 char *default_string;
6275
6276 upb_fielddef *f;
6277};
6278
Chris Fallin91473dc2014-12-12 15:58:26 -08006279static char *upb_strndup(const char *buf, size_t n) {
6280 char *ret = malloc(n + 1);
6281 if (!ret) return NULL;
6282 memcpy(ret, buf, n);
6283 ret[n] = '\0';
6284 return ret;
6285}
6286
Josh Habermane8ed0212015-06-08 17:56:03 -07006287/* Returns a newly allocated string that joins input strings together, for
6288 * example:
6289 * join("Foo.Bar", "Baz") -> "Foo.Bar.Baz"
6290 * join("", "Baz") -> "Baz"
6291 * Caller owns a ref on the returned string. */
Chris Fallin91473dc2014-12-12 15:58:26 -08006292static char *upb_join(const char *base, const char *name) {
6293 if (!base || strlen(base) == 0) {
6294 return upb_strdup(name);
6295 } else {
6296 char *ret = malloc(strlen(base) + strlen(name) + 2);
6297 ret[0] = '\0';
6298 strcat(ret, base);
6299 strcat(ret, ".");
6300 strcat(ret, name);
6301 return ret;
6302 }
6303}
6304
Josh Habermane8ed0212015-06-08 17:56:03 -07006305/* Qualify the defname for all defs starting with offset "start" with "str". */
Josh Haberman94e54b32016-04-14 12:06:09 -07006306static void upb_descreader_qualify(upb_filedef *f, char *str, int32_t start) {
6307 size_t i;
6308 for (i = start; i < upb_filedef_defcount(f); i++) {
6309 upb_def *def = upb_filedef_mutabledef(f, i);
Chris Fallin91473dc2014-12-12 15:58:26 -08006310 char *name = upb_join(str, upb_def_fullname(def));
6311 upb_def_setfullname(def, name, NULL);
6312 free(name);
6313 }
6314}
6315
6316
6317/* upb_descreader ************************************************************/
6318
Chris Fallin91473dc2014-12-12 15:58:26 -08006319static upb_msgdef *upb_descreader_top(upb_descreader *r) {
Josh Habermane8ed0212015-06-08 17:56:03 -07006320 int index;
Chris Fallin91473dc2014-12-12 15:58:26 -08006321 assert(r->stack_len > 1);
Josh Habermane8ed0212015-06-08 17:56:03 -07006322 index = r->stack[r->stack_len-1].start - 1;
Chris Fallin91473dc2014-12-12 15:58:26 -08006323 assert(index >= 0);
Josh Haberman94e54b32016-04-14 12:06:09 -07006324 return upb_downcast_msgdef_mutable(upb_filedef_mutabledef(r->file, index));
Chris Fallin91473dc2014-12-12 15:58:26 -08006325}
6326
6327static upb_def *upb_descreader_last(upb_descreader *r) {
Josh Haberman94e54b32016-04-14 12:06:09 -07006328 return upb_filedef_mutabledef(r->file, upb_filedef_defcount(r->file) - 1);
Chris Fallin91473dc2014-12-12 15:58:26 -08006329}
6330
Josh Habermane8ed0212015-06-08 17:56:03 -07006331/* Start/end handlers for FileDescriptorProto and DescriptorProto (the two
6332 * entities that have names and can contain sub-definitions. */
Chris Fallin91473dc2014-12-12 15:58:26 -08006333void upb_descreader_startcontainer(upb_descreader *r) {
6334 upb_descreader_frame *f = &r->stack[r->stack_len++];
Josh Haberman94e54b32016-04-14 12:06:09 -07006335 f->start = upb_filedef_defcount(r->file);
Chris Fallin91473dc2014-12-12 15:58:26 -08006336 f->name = NULL;
6337}
6338
6339void upb_descreader_endcontainer(upb_descreader *r) {
6340 upb_descreader_frame *f = &r->stack[--r->stack_len];
Josh Haberman94e54b32016-04-14 12:06:09 -07006341 upb_descreader_qualify(r->file, f->name, f->start);
Chris Fallin91473dc2014-12-12 15:58:26 -08006342 free(f->name);
6343 f->name = NULL;
6344}
6345
6346void upb_descreader_setscopename(upb_descreader *r, char *str) {
6347 upb_descreader_frame *f = &r->stack[r->stack_len-1];
6348 free(f->name);
6349 f->name = str;
6350}
6351
Josh Haberman94e54b32016-04-14 12:06:09 -07006352/** Handlers for google.protobuf.FileDescriptorSet. ***************************/
6353
6354static void *fileset_startfile(void *closure, const void *hd) {
6355 upb_descreader *r = closure;
6356 UPB_UNUSED(hd);
6357 r->file = upb_filedef_new(&r->files);
6358 upb_inttable_push(&r->files, upb_value_ptr(r->file));
6359 return r;
6360}
6361
6362/** Handlers for google.protobuf.FileDescriptorProto. *************************/
6363
6364static bool file_start(void *closure, const void *hd) {
Josh Haberman78da6662016-01-13 19:05:43 -08006365 upb_descreader *r = closure;
Chris Fallin91473dc2014-12-12 15:58:26 -08006366 UPB_UNUSED(hd);
6367 upb_descreader_startcontainer(r);
6368 return true;
6369}
6370
Josh Haberman94e54b32016-04-14 12:06:09 -07006371static bool file_end(void *closure, const void *hd, upb_status *status) {
Josh Habermane8ed0212015-06-08 17:56:03 -07006372 upb_descreader *r = closure;
Chris Fallin91473dc2014-12-12 15:58:26 -08006373 UPB_UNUSED(hd);
6374 UPB_UNUSED(status);
Chris Fallin91473dc2014-12-12 15:58:26 -08006375 upb_descreader_endcontainer(r);
6376 return true;
6377}
6378
Josh Haberman94e54b32016-04-14 12:06:09 -07006379static size_t file_onname(void *closure, const void *hd, const char *buf,
6380 size_t n, const upb_bufhandle *handle) {
6381 upb_descreader *r = closure;
6382 char *name;
6383 bool ok;
6384 UPB_UNUSED(hd);
6385 UPB_UNUSED(handle);
6386
6387 name = upb_strndup(buf, n);
6388 /* XXX: see comment at the top of the file. */
6389 ok = upb_filedef_setname(r->file, name, NULL);
6390 UPB_ASSERT_VAR(ok, ok);
6391 return n;
6392}
6393
Chris Fallin91473dc2014-12-12 15:58:26 -08006394static size_t file_onpackage(void *closure, const void *hd, const char *buf,
6395 size_t n, const upb_bufhandle *handle) {
Josh Habermane8ed0212015-06-08 17:56:03 -07006396 upb_descreader *r = closure;
Josh Haberman94e54b32016-04-14 12:06:09 -07006397 char *package;
6398 bool ok;
Chris Fallin91473dc2014-12-12 15:58:26 -08006399 UPB_UNUSED(hd);
6400 UPB_UNUSED(handle);
Josh Haberman94e54b32016-04-14 12:06:09 -07006401
6402 package = upb_strndup(buf, n);
Josh Habermane8ed0212015-06-08 17:56:03 -07006403 /* XXX: see comment at the top of the file. */
Josh Haberman94e54b32016-04-14 12:06:09 -07006404 upb_descreader_setscopename(r, package);
6405 ok = upb_filedef_setpackage(r->file, package, NULL);
6406 UPB_ASSERT_VAR(ok, ok);
Chris Fallin91473dc2014-12-12 15:58:26 -08006407 return n;
6408}
6409
Josh Haberman78da6662016-01-13 19:05:43 -08006410static size_t file_onsyntax(void *closure, const void *hd, const char *buf,
6411 size_t n, const upb_bufhandle *handle) {
6412 upb_descreader *r = closure;
Josh Haberman94e54b32016-04-14 12:06:09 -07006413 bool ok;
Josh Haberman78da6662016-01-13 19:05:43 -08006414 UPB_UNUSED(hd);
6415 UPB_UNUSED(handle);
6416 /* XXX: see comment at the top of the file. */
6417 if (upb_streq("proto2", buf, n)) {
Josh Haberman94e54b32016-04-14 12:06:09 -07006418 ok = upb_filedef_setsyntax(r->file, UPB_SYNTAX_PROTO2, NULL);
Josh Haberman78da6662016-01-13 19:05:43 -08006419 } else if (upb_streq("proto3", buf, n)) {
Josh Haberman94e54b32016-04-14 12:06:09 -07006420 ok = upb_filedef_setsyntax(r->file, UPB_SYNTAX_PROTO3, NULL);
Josh Haberman78da6662016-01-13 19:05:43 -08006421 } else {
Josh Haberman94e54b32016-04-14 12:06:09 -07006422 ok = false;
Josh Haberman78da6662016-01-13 19:05:43 -08006423 }
6424
Josh Haberman94e54b32016-04-14 12:06:09 -07006425 UPB_ASSERT_VAR(ok, ok);
Josh Haberman78da6662016-01-13 19:05:43 -08006426 return n;
6427}
6428
Josh Haberman94e54b32016-04-14 12:06:09 -07006429static void *file_startmsg(void *closure, const void *hd) {
6430 upb_descreader *r = closure;
6431 upb_msgdef *m = upb_msgdef_new(&m);
6432 bool ok = upb_filedef_addmsg(r->file, m, &m, NULL);
6433 UPB_UNUSED(hd);
6434 UPB_ASSERT_VAR(ok, ok);
6435 return r;
6436}
6437
6438static void *file_startenum(void *closure, const void *hd) {
6439 upb_descreader *r = closure;
6440 upb_enumdef *e = upb_enumdef_new(&e);
6441 bool ok = upb_filedef_addenum(r->file, e, &e, NULL);
6442 UPB_UNUSED(hd);
6443 UPB_ASSERT_VAR(ok, ok);
6444 return r;
6445}
6446
6447static void *file_startext(void *closure, const void *hd) {
6448 upb_descreader *r = closure;
6449 bool ok;
6450 r->f = upb_fielddef_new(r);
6451 ok = upb_filedef_addext(r->file, r->f, r, NULL);
6452 UPB_UNUSED(hd);
6453 UPB_ASSERT_VAR(ok, ok);
6454 return r;
6455}
6456
6457/** Handlers for google.protobuf.EnumValueDescriptorProto. *********************/
6458
Chris Fallin91473dc2014-12-12 15:58:26 -08006459static bool enumval_startmsg(void *closure, const void *hd) {
Chris Fallin91473dc2014-12-12 15:58:26 -08006460 upb_descreader *r = closure;
Josh Habermane8ed0212015-06-08 17:56:03 -07006461 UPB_UNUSED(hd);
Chris Fallin91473dc2014-12-12 15:58:26 -08006462 r->saw_number = false;
6463 r->saw_name = false;
6464 return true;
6465}
6466
6467static size_t enumval_onname(void *closure, const void *hd, const char *buf,
6468 size_t n, const upb_bufhandle *handle) {
Josh Habermane8ed0212015-06-08 17:56:03 -07006469 upb_descreader *r = closure;
Chris Fallin91473dc2014-12-12 15:58:26 -08006470 UPB_UNUSED(hd);
6471 UPB_UNUSED(handle);
Josh Habermane8ed0212015-06-08 17:56:03 -07006472 /* XXX: see comment at the top of the file. */
Chris Fallin91473dc2014-12-12 15:58:26 -08006473 free(r->name);
6474 r->name = upb_strndup(buf, n);
6475 r->saw_name = true;
6476 return n;
6477}
6478
6479static bool enumval_onnumber(void *closure, const void *hd, int32_t val) {
Chris Fallin91473dc2014-12-12 15:58:26 -08006480 upb_descreader *r = closure;
Josh Habermane8ed0212015-06-08 17:56:03 -07006481 UPB_UNUSED(hd);
Chris Fallin91473dc2014-12-12 15:58:26 -08006482 r->number = val;
6483 r->saw_number = true;
6484 return true;
6485}
6486
6487static bool enumval_endmsg(void *closure, const void *hd, upb_status *status) {
Chris Fallin91473dc2014-12-12 15:58:26 -08006488 upb_descreader *r = closure;
Josh Habermane8ed0212015-06-08 17:56:03 -07006489 upb_enumdef *e;
6490 UPB_UNUSED(hd);
6491
Chris Fallin91473dc2014-12-12 15:58:26 -08006492 if(!r->saw_number || !r->saw_name) {
6493 upb_status_seterrmsg(status, "Enum value missing name or number.");
6494 return false;
6495 }
Josh Habermane8ed0212015-06-08 17:56:03 -07006496 e = upb_downcast_enumdef_mutable(upb_descreader_last(r));
Chris Fallin91473dc2014-12-12 15:58:26 -08006497 upb_enumdef_addval(e, r->name, r->number, status);
6498 free(r->name);
6499 r->name = NULL;
6500 return true;
6501}
6502
Josh Haberman94e54b32016-04-14 12:06:09 -07006503/** Handlers for google.protobuf.EnumDescriptorProto. *************************/
Chris Fallin91473dc2014-12-12 15:58:26 -08006504
6505static bool enum_endmsg(void *closure, const void *hd, upb_status *status) {
Chris Fallin91473dc2014-12-12 15:58:26 -08006506 upb_descreader *r = closure;
Josh Habermane8ed0212015-06-08 17:56:03 -07006507 upb_enumdef *e;
6508 UPB_UNUSED(hd);
6509
6510 e = upb_downcast_enumdef_mutable(upb_descreader_last(r));
Chris Fallin91473dc2014-12-12 15:58:26 -08006511 if (upb_def_fullname(upb_descreader_last(r)) == NULL) {
6512 upb_status_seterrmsg(status, "Enum had no name.");
6513 return false;
6514 }
6515 if (upb_enumdef_numvals(e) == 0) {
6516 upb_status_seterrmsg(status, "Enum had no values.");
6517 return false;
6518 }
6519 return true;
6520}
6521
6522static size_t enum_onname(void *closure, const void *hd, const char *buf,
6523 size_t n, const upb_bufhandle *handle) {
Josh Habermane8ed0212015-06-08 17:56:03 -07006524 upb_descreader *r = closure;
6525 char *fullname = upb_strndup(buf, n);
Chris Fallin91473dc2014-12-12 15:58:26 -08006526 UPB_UNUSED(hd);
6527 UPB_UNUSED(handle);
Josh Habermane8ed0212015-06-08 17:56:03 -07006528 /* XXX: see comment at the top of the file. */
Chris Fallin91473dc2014-12-12 15:58:26 -08006529 upb_def_setfullname(upb_descreader_last(r), fullname, NULL);
6530 free(fullname);
6531 return n;
6532}
6533
Josh Haberman94e54b32016-04-14 12:06:09 -07006534/** Handlers for google.protobuf.FieldDescriptorProto *************************/
6535
Chris Fallin91473dc2014-12-12 15:58:26 -08006536static bool field_startmsg(void *closure, const void *hd) {
Chris Fallin91473dc2014-12-12 15:58:26 -08006537 upb_descreader *r = closure;
Josh Habermane8ed0212015-06-08 17:56:03 -07006538 UPB_UNUSED(hd);
Josh Haberman94e54b32016-04-14 12:06:09 -07006539 assert(r->f);
Chris Fallin91473dc2014-12-12 15:58:26 -08006540 free(r->default_string);
6541 r->default_string = NULL;
6542
Josh Habermane8ed0212015-06-08 17:56:03 -07006543 /* fielddefs default to packed, but descriptors default to non-packed. */
Chris Fallin91473dc2014-12-12 15:58:26 -08006544 upb_fielddef_setpacked(r->f, false);
6545 return true;
6546}
6547
Josh Habermane8ed0212015-06-08 17:56:03 -07006548/* Converts the default value in string "str" into "d". Passes a ref on str.
6549 * Returns true on success. */
Chris Fallin91473dc2014-12-12 15:58:26 -08006550static bool parse_default(char *str, upb_fielddef *f) {
6551 bool success = true;
6552 char *end;
6553 switch (upb_fielddef_type(f)) {
6554 case UPB_TYPE_INT32: {
6555 long val = strtol(str, &end, 0);
6556 if (val > INT32_MAX || val < INT32_MIN || errno == ERANGE || *end)
6557 success = false;
6558 else
6559 upb_fielddef_setdefaultint32(f, val);
6560 break;
6561 }
6562 case UPB_TYPE_INT64: {
Josh Habermane8ed0212015-06-08 17:56:03 -07006563 /* XXX: Need to write our own strtoll, since it's not available in c89. */
6564 long long val = strtol(str, &end, 0);
Chris Fallin91473dc2014-12-12 15:58:26 -08006565 if (val > INT64_MAX || val < INT64_MIN || errno == ERANGE || *end)
6566 success = false;
6567 else
6568 upb_fielddef_setdefaultint64(f, val);
6569 break;
6570 }
6571 case UPB_TYPE_UINT32: {
Chris Fallind3262772015-05-14 18:24:26 -07006572 unsigned long val = strtoul(str, &end, 0);
Chris Fallin91473dc2014-12-12 15:58:26 -08006573 if (val > UINT32_MAX || errno == ERANGE || *end)
6574 success = false;
6575 else
6576 upb_fielddef_setdefaultuint32(f, val);
6577 break;
6578 }
6579 case UPB_TYPE_UINT64: {
Josh Habermane8ed0212015-06-08 17:56:03 -07006580 /* XXX: Need to write our own strtoull, since it's not available in c89. */
6581 unsigned long long val = strtoul(str, &end, 0);
Chris Fallin91473dc2014-12-12 15:58:26 -08006582 if (val > UINT64_MAX || errno == ERANGE || *end)
6583 success = false;
6584 else
6585 upb_fielddef_setdefaultuint64(f, val);
6586 break;
6587 }
6588 case UPB_TYPE_DOUBLE: {
6589 double val = strtod(str, &end);
6590 if (errno == ERANGE || *end)
6591 success = false;
6592 else
6593 upb_fielddef_setdefaultdouble(f, val);
6594 break;
6595 }
6596 case UPB_TYPE_FLOAT: {
Josh Habermane8ed0212015-06-08 17:56:03 -07006597 /* XXX: Need to write our own strtof, since it's not available in c89. */
6598 float val = strtod(str, &end);
Chris Fallin91473dc2014-12-12 15:58:26 -08006599 if (errno == ERANGE || *end)
6600 success = false;
6601 else
6602 upb_fielddef_setdefaultfloat(f, val);
6603 break;
6604 }
6605 case UPB_TYPE_BOOL: {
6606 if (strcmp(str, "false") == 0)
6607 upb_fielddef_setdefaultbool(f, false);
6608 else if (strcmp(str, "true") == 0)
6609 upb_fielddef_setdefaultbool(f, true);
6610 else
6611 success = false;
6612 break;
6613 }
6614 default: abort();
6615 }
6616 return success;
6617}
6618
6619static bool field_endmsg(void *closure, const void *hd, upb_status *status) {
Chris Fallin91473dc2014-12-12 15:58:26 -08006620 upb_descreader *r = closure;
6621 upb_fielddef *f = r->f;
Josh Habermane8ed0212015-06-08 17:56:03 -07006622 UPB_UNUSED(hd);
6623
6624 /* TODO: verify that all required fields were present. */
Chris Fallin91473dc2014-12-12 15:58:26 -08006625 assert(upb_fielddef_number(f) != 0);
6626 assert(upb_fielddef_name(f) != NULL);
6627 assert((upb_fielddef_subdefname(f) != NULL) == upb_fielddef_hassubdef(f));
6628
6629 if (r->default_string) {
6630 if (upb_fielddef_issubmsg(f)) {
6631 upb_status_seterrmsg(status, "Submessages cannot have defaults.");
6632 return false;
6633 }
6634 if (upb_fielddef_isstring(f) || upb_fielddef_type(f) == UPB_TYPE_ENUM) {
6635 upb_fielddef_setdefaultcstr(f, r->default_string, NULL);
6636 } else {
6637 if (r->default_string && !parse_default(r->default_string, f)) {
Josh Habermane8ed0212015-06-08 17:56:03 -07006638 /* We don't worry too much about giving a great error message since the
6639 * compiler should have ensured this was correct. */
Chris Fallin91473dc2014-12-12 15:58:26 -08006640 upb_status_seterrmsg(status, "Error converting default value.");
6641 return false;
6642 }
6643 }
6644 }
6645 return true;
6646}
6647
6648static bool field_onlazy(void *closure, const void *hd, bool val) {
Chris Fallin91473dc2014-12-12 15:58:26 -08006649 upb_descreader *r = closure;
Josh Habermane8ed0212015-06-08 17:56:03 -07006650 UPB_UNUSED(hd);
6651
Chris Fallin91473dc2014-12-12 15:58:26 -08006652 upb_fielddef_setlazy(r->f, val);
6653 return true;
6654}
6655
6656static bool field_onpacked(void *closure, const void *hd, bool val) {
Chris Fallin91473dc2014-12-12 15:58:26 -08006657 upb_descreader *r = closure;
Josh Habermane8ed0212015-06-08 17:56:03 -07006658 UPB_UNUSED(hd);
6659
Chris Fallin91473dc2014-12-12 15:58:26 -08006660 upb_fielddef_setpacked(r->f, val);
6661 return true;
6662}
6663
6664static bool field_ontype(void *closure, const void *hd, int32_t val) {
Chris Fallin91473dc2014-12-12 15:58:26 -08006665 upb_descreader *r = closure;
Josh Habermane8ed0212015-06-08 17:56:03 -07006666 UPB_UNUSED(hd);
6667
Chris Fallin91473dc2014-12-12 15:58:26 -08006668 upb_fielddef_setdescriptortype(r->f, val);
6669 return true;
6670}
6671
6672static bool field_onlabel(void *closure, const void *hd, int32_t val) {
Chris Fallin91473dc2014-12-12 15:58:26 -08006673 upb_descreader *r = closure;
Josh Habermane8ed0212015-06-08 17:56:03 -07006674 UPB_UNUSED(hd);
6675
Chris Fallin91473dc2014-12-12 15:58:26 -08006676 upb_fielddef_setlabel(r->f, val);
6677 return true;
6678}
6679
6680static bool field_onnumber(void *closure, const void *hd, int32_t val) {
Chris Fallin91473dc2014-12-12 15:58:26 -08006681 upb_descreader *r = closure;
Josh Haberman94e54b32016-04-14 12:06:09 -07006682 bool ok;
Josh Habermane8ed0212015-06-08 17:56:03 -07006683 UPB_UNUSED(hd);
6684
Josh Haberman94e54b32016-04-14 12:06:09 -07006685 ok = upb_fielddef_setnumber(r->f, val, NULL);
Chris Fallin91473dc2014-12-12 15:58:26 -08006686 UPB_ASSERT_VAR(ok, ok);
6687 return true;
6688}
6689
6690static size_t field_onname(void *closure, const void *hd, const char *buf,
6691 size_t n, const upb_bufhandle *handle) {
Josh Habermane8ed0212015-06-08 17:56:03 -07006692 upb_descreader *r = closure;
6693 char *name = upb_strndup(buf, n);
Chris Fallin91473dc2014-12-12 15:58:26 -08006694 UPB_UNUSED(hd);
6695 UPB_UNUSED(handle);
Josh Habermane8ed0212015-06-08 17:56:03 -07006696
6697 /* XXX: see comment at the top of the file. */
Chris Fallin91473dc2014-12-12 15:58:26 -08006698 upb_fielddef_setname(r->f, name, NULL);
6699 free(name);
6700 return n;
6701}
6702
6703static size_t field_ontypename(void *closure, const void *hd, const char *buf,
6704 size_t n, const upb_bufhandle *handle) {
Josh Habermane8ed0212015-06-08 17:56:03 -07006705 upb_descreader *r = closure;
6706 char *name = upb_strndup(buf, n);
Chris Fallin91473dc2014-12-12 15:58:26 -08006707 UPB_UNUSED(hd);
6708 UPB_UNUSED(handle);
Josh Habermane8ed0212015-06-08 17:56:03 -07006709
6710 /* XXX: see comment at the top of the file. */
Chris Fallin91473dc2014-12-12 15:58:26 -08006711 upb_fielddef_setsubdefname(r->f, name, NULL);
6712 free(name);
6713 return n;
6714}
6715
6716static size_t field_onextendee(void *closure, const void *hd, const char *buf,
6717 size_t n, const upb_bufhandle *handle) {
Josh Habermane8ed0212015-06-08 17:56:03 -07006718 upb_descreader *r = closure;
6719 char *name = upb_strndup(buf, n);
Chris Fallin91473dc2014-12-12 15:58:26 -08006720 UPB_UNUSED(hd);
6721 UPB_UNUSED(handle);
Josh Habermane8ed0212015-06-08 17:56:03 -07006722
6723 /* XXX: see comment at the top of the file. */
Chris Fallin91473dc2014-12-12 15:58:26 -08006724 upb_fielddef_setcontainingtypename(r->f, name, NULL);
6725 free(name);
6726 return n;
6727}
6728
6729static size_t field_ondefaultval(void *closure, const void *hd, const char *buf,
6730 size_t n, const upb_bufhandle *handle) {
Josh Habermane8ed0212015-06-08 17:56:03 -07006731 upb_descreader *r = closure;
Chris Fallin91473dc2014-12-12 15:58:26 -08006732 UPB_UNUSED(hd);
6733 UPB_UNUSED(handle);
Josh Habermane8ed0212015-06-08 17:56:03 -07006734
6735 /* Have to convert from string to the correct type, but we might not know the
6736 * type yet, so we save it as a string until the end of the field.
6737 * XXX: see comment at the top of the file. */
Chris Fallin91473dc2014-12-12 15:58:26 -08006738 free(r->default_string);
6739 r->default_string = upb_strndup(buf, n);
6740 return n;
6741}
6742
Josh Haberman94e54b32016-04-14 12:06:09 -07006743/** Handlers for google.protobuf.DescriptorProto ******************************/
6744
6745static bool msg_start(void *closure, const void *hd) {
Chris Fallin91473dc2014-12-12 15:58:26 -08006746 upb_descreader *r = closure;
Josh Habermane8ed0212015-06-08 17:56:03 -07006747 UPB_UNUSED(hd);
6748
Chris Fallin91473dc2014-12-12 15:58:26 -08006749 upb_descreader_startcontainer(r);
6750 return true;
6751}
6752
Josh Haberman94e54b32016-04-14 12:06:09 -07006753static bool msg_end(void *closure, const void *hd, upb_status *status) {
Chris Fallin91473dc2014-12-12 15:58:26 -08006754 upb_descreader *r = closure;
6755 upb_msgdef *m = upb_descreader_top(r);
Josh Habermane8ed0212015-06-08 17:56:03 -07006756 UPB_UNUSED(hd);
6757
6758 if(!upb_def_fullname(upb_msgdef_upcast_mutable(m))) {
Chris Fallin91473dc2014-12-12 15:58:26 -08006759 upb_status_seterrmsg(status, "Encountered message with no name.");
6760 return false;
6761 }
6762 upb_descreader_endcontainer(r);
6763 return true;
6764}
6765
Josh Haberman94e54b32016-04-14 12:06:09 -07006766static size_t msg_name(void *closure, const void *hd, const char *buf,
6767 size_t n, const upb_bufhandle *handle) {
Chris Fallin91473dc2014-12-12 15:58:26 -08006768 upb_descreader *r = closure;
6769 upb_msgdef *m = upb_descreader_top(r);
Josh Habermane8ed0212015-06-08 17:56:03 -07006770 /* XXX: see comment at the top of the file. */
Chris Fallin91473dc2014-12-12 15:58:26 -08006771 char *name = upb_strndup(buf, n);
Josh Habermane8ed0212015-06-08 17:56:03 -07006772 UPB_UNUSED(hd);
6773 UPB_UNUSED(handle);
6774
6775 upb_def_setfullname(upb_msgdef_upcast_mutable(m), name, NULL);
6776 upb_descreader_setscopename(r, name); /* Passes ownership of name. */
Chris Fallin91473dc2014-12-12 15:58:26 -08006777 return n;
6778}
6779
Josh Haberman94e54b32016-04-14 12:06:09 -07006780static void *msg_startmsg(void *closure, const void *hd) {
6781 upb_descreader *r = closure;
6782 upb_msgdef *m = upb_msgdef_new(&m);
6783 bool ok = upb_filedef_addmsg(r->file, m, &m, NULL);
6784 UPB_UNUSED(hd);
6785 UPB_ASSERT_VAR(ok, ok);
6786 return r;
6787}
6788
6789static void *msg_startext(void *closure, const void *hd) {
6790 upb_descreader *r = closure;
6791 upb_fielddef *f = upb_fielddef_new(&f);
6792 bool ok = upb_filedef_addext(r->file, f, &f, NULL);
6793 UPB_UNUSED(hd);
6794 UPB_ASSERT_VAR(ok, ok);
6795 return r;
6796}
6797
6798static void *msg_startfield(void *closure, const void *hd) {
6799 upb_descreader *r = closure;
6800 r->f = upb_fielddef_new(&r->f);
6801 /* We can't add the new field to the message until its name/number are
6802 * filled in. */
6803 UPB_UNUSED(hd);
6804 return r;
6805}
6806
6807static bool msg_endfield(void *closure, const void *hd) {
Chris Fallin91473dc2014-12-12 15:58:26 -08006808 upb_descreader *r = closure;
6809 upb_msgdef *m = upb_descreader_top(r);
Josh Habermane8ed0212015-06-08 17:56:03 -07006810 UPB_UNUSED(hd);
6811
Josh Haberman94e54b32016-04-14 12:06:09 -07006812 upb_msgdef_addfield(m, r->f, &r->f, NULL);
Chris Fallin91473dc2014-12-12 15:58:26 -08006813 r->f = NULL;
6814 return true;
6815}
6816
Josh Habermane8ed0212015-06-08 17:56:03 -07006817
Josh Haberman94e54b32016-04-14 12:06:09 -07006818/** Code to register handlers *************************************************/
Chris Fallin91473dc2014-12-12 15:58:26 -08006819
Josh Haberman94e54b32016-04-14 12:06:09 -07006820#define F(msg, field) upbdefs_google_protobuf_ ## msg ## _f_ ## field(m)
Chris Fallin91473dc2014-12-12 15:58:26 -08006821
6822static void reghandlers(const void *closure, upb_handlers *h) {
Chris Fallin91473dc2014-12-12 15:58:26 -08006823 const upb_msgdef *m = upb_handlers_msgdef(h);
Josh Haberman94e54b32016-04-14 12:06:09 -07006824 UPB_UNUSED(closure);
Chris Fallin91473dc2014-12-12 15:58:26 -08006825
Josh Haberman94e54b32016-04-14 12:06:09 -07006826 if (upbdefs_google_protobuf_FileDescriptorSet_is(m)) {
6827 upb_handlers_setstartsubmsg(h, F(FileDescriptorSet, file),
6828 &fileset_startfile, NULL);
6829 } else if (upbdefs_google_protobuf_DescriptorProto_is(m)) {
6830 upb_handlers_setstartmsg(h, &msg_start, NULL);
6831 upb_handlers_setendmsg(h, &msg_end, NULL);
6832 upb_handlers_setstring(h, F(DescriptorProto, name), &msg_name, NULL);
6833 upb_handlers_setstartsubmsg(h, F(DescriptorProto, extension), &msg_startext,
6834 NULL);
6835 upb_handlers_setstartsubmsg(h, F(DescriptorProto, nested_type),
6836 &msg_startmsg, NULL);
6837 upb_handlers_setstartsubmsg(h, F(DescriptorProto, field),
6838 &msg_startfield, NULL);
6839 upb_handlers_setendsubmsg(h, F(DescriptorProto, field),
6840 &msg_endfield, NULL);
6841 upb_handlers_setstartsubmsg(h, F(DescriptorProto, enum_type),
6842 &file_startenum, NULL);
6843 } else if (upbdefs_google_protobuf_FileDescriptorProto_is(m)) {
6844 upb_handlers_setstartmsg(h, &file_start, NULL);
6845 upb_handlers_setendmsg(h, &file_end, NULL);
6846 upb_handlers_setstring(h, F(FileDescriptorProto, name), &file_onname,
Chris Fallin91473dc2014-12-12 15:58:26 -08006847 NULL);
Josh Haberman94e54b32016-04-14 12:06:09 -07006848 upb_handlers_setstring(h, F(FileDescriptorProto, package), &file_onpackage,
Josh Haberman78da6662016-01-13 19:05:43 -08006849 NULL);
Josh Haberman94e54b32016-04-14 12:06:09 -07006850 upb_handlers_setstring(h, F(FileDescriptorProto, syntax), &file_onsyntax,
6851 NULL);
6852 upb_handlers_setstartsubmsg(h, F(FileDescriptorProto, message_type),
6853 &file_startmsg, NULL);
6854 upb_handlers_setstartsubmsg(h, F(FileDescriptorProto, enum_type),
6855 &file_startenum, NULL);
6856 upb_handlers_setstartsubmsg(h, F(FileDescriptorProto, extension),
6857 &file_startext, NULL);
6858 } else if (upbdefs_google_protobuf_EnumValueDescriptorProto_is(m)) {
Chris Fallin91473dc2014-12-12 15:58:26 -08006859 upb_handlers_setstartmsg(h, &enumval_startmsg, NULL);
6860 upb_handlers_setendmsg(h, &enumval_endmsg, NULL);
Josh Haberman94e54b32016-04-14 12:06:09 -07006861 upb_handlers_setstring(h, F(EnumValueDescriptorProto, name), &enumval_onname, NULL);
6862 upb_handlers_setint32(h, F(EnumValueDescriptorProto, number), &enumval_onnumber,
Chris Fallin91473dc2014-12-12 15:58:26 -08006863 NULL);
Josh Haberman94e54b32016-04-14 12:06:09 -07006864 } else if (upbdefs_google_protobuf_EnumDescriptorProto_is(m)) {
Chris Fallin91473dc2014-12-12 15:58:26 -08006865 upb_handlers_setendmsg(h, &enum_endmsg, NULL);
Josh Haberman94e54b32016-04-14 12:06:09 -07006866 upb_handlers_setstring(h, F(EnumDescriptorProto, name), &enum_onname, NULL);
6867 } else if (upbdefs_google_protobuf_FieldDescriptorProto_is(m)) {
Chris Fallin91473dc2014-12-12 15:58:26 -08006868 upb_handlers_setstartmsg(h, &field_startmsg, NULL);
6869 upb_handlers_setendmsg(h, &field_endmsg, NULL);
Josh Haberman94e54b32016-04-14 12:06:09 -07006870 upb_handlers_setint32(h, F(FieldDescriptorProto, type), &field_ontype,
Chris Fallin91473dc2014-12-12 15:58:26 -08006871 NULL);
Josh Haberman94e54b32016-04-14 12:06:09 -07006872 upb_handlers_setint32(h, F(FieldDescriptorProto, label), &field_onlabel,
Chris Fallin91473dc2014-12-12 15:58:26 -08006873 NULL);
Josh Haberman94e54b32016-04-14 12:06:09 -07006874 upb_handlers_setint32(h, F(FieldDescriptorProto, number), &field_onnumber,
Chris Fallin91473dc2014-12-12 15:58:26 -08006875 NULL);
Josh Haberman94e54b32016-04-14 12:06:09 -07006876 upb_handlers_setstring(h, F(FieldDescriptorProto, name), &field_onname,
Chris Fallin91473dc2014-12-12 15:58:26 -08006877 NULL);
Josh Haberman94e54b32016-04-14 12:06:09 -07006878 upb_handlers_setstring(h, F(FieldDescriptorProto, type_name),
Chris Fallin91473dc2014-12-12 15:58:26 -08006879 &field_ontypename, NULL);
Josh Haberman94e54b32016-04-14 12:06:09 -07006880 upb_handlers_setstring(h, F(FieldDescriptorProto, extendee),
Chris Fallin91473dc2014-12-12 15:58:26 -08006881 &field_onextendee, NULL);
Josh Haberman94e54b32016-04-14 12:06:09 -07006882 upb_handlers_setstring(h, F(FieldDescriptorProto, default_value),
Chris Fallin91473dc2014-12-12 15:58:26 -08006883 &field_ondefaultval, NULL);
Josh Haberman94e54b32016-04-14 12:06:09 -07006884 } else if (upbdefs_google_protobuf_FieldOptions_is(m)) {
6885 upb_handlers_setbool(h, F(FieldOptions, lazy), &field_onlazy, NULL);
6886 upb_handlers_setbool(h, F(FieldOptions, packed), &field_onpacked, NULL);
Chris Fallin91473dc2014-12-12 15:58:26 -08006887 }
Josh Haberman94e54b32016-04-14 12:06:09 -07006888
6889 assert(upb_ok(upb_handlers_status(h)));
Chris Fallin91473dc2014-12-12 15:58:26 -08006890}
6891
Josh Haberman94e54b32016-04-14 12:06:09 -07006892#undef F
Chris Fallin91473dc2014-12-12 15:58:26 -08006893
Chris Fallind3262772015-05-14 18:24:26 -07006894void descreader_cleanup(void *_r) {
6895 upb_descreader *r = _r;
Josh Haberman94e54b32016-04-14 12:06:09 -07006896 size_t i;
6897
6898 for (i = 0; i < upb_descreader_filecount(r); i++) {
6899 upb_filedef_unref(upb_descreader_file(r, i), &r->files);
6900 }
6901
Chris Fallind3262772015-05-14 18:24:26 -07006902 free(r->name);
Josh Haberman94e54b32016-04-14 12:06:09 -07006903 upb_inttable_uninit(&r->files);
Chris Fallind3262772015-05-14 18:24:26 -07006904 free(r->default_string);
6905 while (r->stack_len > 0) {
6906 upb_descreader_frame *f = &r->stack[--r->stack_len];
6907 free(f->name);
6908 }
6909}
6910
6911
6912/* Public API ****************************************************************/
6913
6914upb_descreader *upb_descreader_create(upb_env *e, const upb_handlers *h) {
6915 upb_descreader *r = upb_env_malloc(e, sizeof(upb_descreader));
6916 if (!r || !upb_env_addcleanup(e, descreader_cleanup, r)) {
6917 return NULL;
6918 }
6919
Josh Haberman94e54b32016-04-14 12:06:09 -07006920 upb_inttable_init(&r->files, UPB_CTYPE_PTR);
Chris Fallind3262772015-05-14 18:24:26 -07006921 upb_sink_reset(upb_descreader_input(r), h, r);
6922 r->stack_len = 0;
6923 r->name = NULL;
6924 r->default_string = NULL;
6925
6926 return r;
6927}
6928
Josh Haberman94e54b32016-04-14 12:06:09 -07006929size_t upb_descreader_filecount(const upb_descreader *r) {
6930 return upb_inttable_count(&r->files);
6931}
6932
6933upb_filedef *upb_descreader_file(const upb_descreader *r, size_t i) {
6934 upb_value v;
6935 if (upb_inttable_lookup(&r->files, i, &v)) {
6936 return upb_value_getptr(v);
6937 } else {
6938 return NULL;
6939 }
Chris Fallind3262772015-05-14 18:24:26 -07006940}
6941
6942upb_sink *upb_descreader_input(upb_descreader *r) {
6943 return &r->sink;
6944}
6945
Chris Fallin91473dc2014-12-12 15:58:26 -08006946const upb_handlers *upb_descreader_newhandlers(const void *owner) {
Josh Haberman94e54b32016-04-14 12:06:09 -07006947 const upb_msgdef *m = upbdefs_google_protobuf_FileDescriptorSet_get(&m);
6948 const upb_handlers *h = upb_handlers_newfrozen(m, owner, reghandlers, NULL);
6949 upb_msgdef_unref(m, &m);
Chris Fallin91473dc2014-12-12 15:58:26 -08006950 return h;
6951}
6952/*
Josh Haberman181c7f22015-07-15 11:05:10 -07006953** protobuf decoder bytecode compiler
6954**
6955** Code to compile a upb::Handlers into bytecode for decoding a protobuf
6956** according to that specific schema and destination handlers.
6957**
6958** Compiling to bytecode is always the first step. If we are using the
6959** interpreted decoder we leave it as bytecode and interpret that. If we are
6960** using a JIT decoder we use a code generator to turn the bytecode into native
6961** code, LLVM IR, etc.
6962**
6963** Bytecode definition is in decoder.int.h.
6964*/
Chris Fallin91473dc2014-12-12 15:58:26 -08006965
6966#include <stdarg.h>
6967
6968#ifdef UPB_DUMP_BYTECODE
6969#include <stdio.h>
6970#endif
6971
6972#define MAXLABEL 5
6973#define EMPTYLABEL -1
6974
6975/* mgroup *********************************************************************/
6976
6977static void freegroup(upb_refcounted *r) {
6978 mgroup *g = (mgroup*)r;
6979 upb_inttable_uninit(&g->methods);
6980#ifdef UPB_USE_JIT_X64
6981 upb_pbdecoder_freejit(g);
6982#endif
6983 free(g->bytecode);
6984 free(g);
6985}
6986
6987static void visitgroup(const upb_refcounted *r, upb_refcounted_visit *visit,
6988 void *closure) {
6989 const mgroup *g = (const mgroup*)r;
6990 upb_inttable_iter i;
6991 upb_inttable_begin(&i, &g->methods);
6992 for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
6993 upb_pbdecodermethod *method = upb_value_getptr(upb_inttable_iter_value(&i));
Josh Habermane8ed0212015-06-08 17:56:03 -07006994 visit(r, upb_pbdecodermethod_upcast(method), closure);
Chris Fallin91473dc2014-12-12 15:58:26 -08006995 }
6996}
6997
6998mgroup *newgroup(const void *owner) {
6999 mgroup *g = malloc(sizeof(*g));
7000 static const struct upb_refcounted_vtbl vtbl = {visitgroup, freegroup};
Josh Habermane8ed0212015-06-08 17:56:03 -07007001 upb_refcounted_init(mgroup_upcast_mutable(g), &vtbl, owner);
Chris Fallin91473dc2014-12-12 15:58:26 -08007002 upb_inttable_init(&g->methods, UPB_CTYPE_PTR);
7003 g->bytecode = NULL;
7004 g->bytecode_end = NULL;
7005 return g;
7006}
7007
7008
7009/* upb_pbdecodermethod ********************************************************/
7010
7011static void freemethod(upb_refcounted *r) {
7012 upb_pbdecodermethod *method = (upb_pbdecodermethod*)r;
Chris Fallin91473dc2014-12-12 15:58:26 -08007013
7014 if (method->dest_handlers_) {
7015 upb_handlers_unref(method->dest_handlers_, method);
7016 }
7017
7018 upb_inttable_uninit(&method->dispatch);
7019 free(method);
7020}
7021
7022static void visitmethod(const upb_refcounted *r, upb_refcounted_visit *visit,
7023 void *closure) {
7024 const upb_pbdecodermethod *m = (const upb_pbdecodermethod*)r;
7025 visit(r, m->group, closure);
7026}
7027
7028static upb_pbdecodermethod *newmethod(const upb_handlers *dest_handlers,
7029 mgroup *group) {
7030 static const struct upb_refcounted_vtbl vtbl = {visitmethod, freemethod};
7031 upb_pbdecodermethod *ret = malloc(sizeof(*ret));
Josh Habermane8ed0212015-06-08 17:56:03 -07007032 upb_refcounted_init(upb_pbdecodermethod_upcast_mutable(ret), &vtbl, &ret);
Chris Fallin91473dc2014-12-12 15:58:26 -08007033 upb_byteshandler_init(&ret->input_handler_);
7034
Josh Habermane8ed0212015-06-08 17:56:03 -07007035 /* The method references the group and vice-versa, in a circular reference. */
Chris Fallin91473dc2014-12-12 15:58:26 -08007036 upb_ref2(ret, group);
7037 upb_ref2(group, ret);
7038 upb_inttable_insertptr(&group->methods, dest_handlers, upb_value_ptr(ret));
Josh Habermane8ed0212015-06-08 17:56:03 -07007039 upb_pbdecodermethod_unref(ret, &ret);
Chris Fallin91473dc2014-12-12 15:58:26 -08007040
Josh Habermane8ed0212015-06-08 17:56:03 -07007041 ret->group = mgroup_upcast_mutable(group);
Chris Fallin91473dc2014-12-12 15:58:26 -08007042 ret->dest_handlers_ = dest_handlers;
Josh Habermane8ed0212015-06-08 17:56:03 -07007043 ret->is_native_ = false; /* If we JIT, it will update this later. */
Chris Fallin91473dc2014-12-12 15:58:26 -08007044 upb_inttable_init(&ret->dispatch, UPB_CTYPE_UINT64);
7045
7046 if (ret->dest_handlers_) {
7047 upb_handlers_ref(ret->dest_handlers_, ret);
7048 }
7049 return ret;
7050}
7051
Chris Fallin91473dc2014-12-12 15:58:26 -08007052const upb_handlers *upb_pbdecodermethod_desthandlers(
7053 const upb_pbdecodermethod *m) {
7054 return m->dest_handlers_;
7055}
7056
7057const upb_byteshandler *upb_pbdecodermethod_inputhandler(
7058 const upb_pbdecodermethod *m) {
7059 return &m->input_handler_;
7060}
7061
7062bool upb_pbdecodermethod_isnative(const upb_pbdecodermethod *m) {
7063 return m->is_native_;
7064}
7065
7066const upb_pbdecodermethod *upb_pbdecodermethod_new(
7067 const upb_pbdecodermethodopts *opts, const void *owner) {
Josh Habermane8ed0212015-06-08 17:56:03 -07007068 const upb_pbdecodermethod *ret;
Chris Fallin91473dc2014-12-12 15:58:26 -08007069 upb_pbcodecache cache;
Josh Habermane8ed0212015-06-08 17:56:03 -07007070
Chris Fallin91473dc2014-12-12 15:58:26 -08007071 upb_pbcodecache_init(&cache);
Josh Habermane8ed0212015-06-08 17:56:03 -07007072 ret = upb_pbcodecache_getdecodermethod(&cache, opts);
Chris Fallin91473dc2014-12-12 15:58:26 -08007073 upb_pbdecodermethod_ref(ret, owner);
7074 upb_pbcodecache_uninit(&cache);
7075 return ret;
7076}
7077
7078
7079/* bytecode compiler **********************************************************/
7080
Josh Habermane8ed0212015-06-08 17:56:03 -07007081/* Data used only at compilation time. */
Chris Fallin91473dc2014-12-12 15:58:26 -08007082typedef struct {
7083 mgroup *group;
7084
7085 uint32_t *pc;
7086 int fwd_labels[MAXLABEL];
7087 int back_labels[MAXLABEL];
7088
Josh Habermane8ed0212015-06-08 17:56:03 -07007089 /* For fields marked "lazy", parse them lazily or eagerly? */
Chris Fallin91473dc2014-12-12 15:58:26 -08007090 bool lazy;
7091} compiler;
7092
7093static compiler *newcompiler(mgroup *group, bool lazy) {
7094 compiler *ret = malloc(sizeof(*ret));
Josh Habermane8ed0212015-06-08 17:56:03 -07007095 int i;
7096
Chris Fallin91473dc2014-12-12 15:58:26 -08007097 ret->group = group;
7098 ret->lazy = lazy;
Josh Habermane8ed0212015-06-08 17:56:03 -07007099 for (i = 0; i < MAXLABEL; i++) {
Chris Fallin91473dc2014-12-12 15:58:26 -08007100 ret->fwd_labels[i] = EMPTYLABEL;
7101 ret->back_labels[i] = EMPTYLABEL;
7102 }
7103 return ret;
7104}
7105
7106static void freecompiler(compiler *c) {
7107 free(c);
7108}
7109
7110const size_t ptr_words = sizeof(void*) / sizeof(uint32_t);
7111
Josh Habermane8ed0212015-06-08 17:56:03 -07007112/* How many words an instruction is. */
Chris Fallin91473dc2014-12-12 15:58:26 -08007113static int instruction_len(uint32_t instr) {
7114 switch (getop(instr)) {
7115 case OP_SETDISPATCH: return 1 + ptr_words;
7116 case OP_TAGN: return 3;
7117 case OP_SETBIGGROUPNUM: return 2;
7118 default: return 1;
7119 }
7120}
7121
7122bool op_has_longofs(int32_t instruction) {
7123 switch (getop(instruction)) {
7124 case OP_CALL:
7125 case OP_BRANCH:
7126 case OP_CHECKDELIM:
7127 return true;
Josh Habermane8ed0212015-06-08 17:56:03 -07007128 /* The "tag" instructions only have 8 bytes available for the jump target,
7129 * but that is ok because these opcodes only require short jumps. */
Chris Fallin91473dc2014-12-12 15:58:26 -08007130 case OP_TAG1:
7131 case OP_TAG2:
7132 case OP_TAGN:
7133 return false;
7134 default:
7135 assert(false);
7136 return false;
7137 }
7138}
7139
7140static int32_t getofs(uint32_t instruction) {
7141 if (op_has_longofs(instruction)) {
7142 return (int32_t)instruction >> 8;
7143 } else {
7144 return (int8_t)(instruction >> 8);
7145 }
7146}
7147
7148static void setofs(uint32_t *instruction, int32_t ofs) {
7149 if (op_has_longofs(*instruction)) {
7150 *instruction = getop(*instruction) | ofs << 8;
7151 } else {
7152 *instruction = (*instruction & ~0xff00) | ((ofs & 0xff) << 8);
7153 }
Josh Habermane8ed0212015-06-08 17:56:03 -07007154 assert(getofs(*instruction) == ofs); /* Would fail in cases of overflow. */
Chris Fallin91473dc2014-12-12 15:58:26 -08007155}
7156
7157static uint32_t pcofs(compiler *c) { return c->pc - c->group->bytecode; }
7158
Josh Habermane8ed0212015-06-08 17:56:03 -07007159/* Defines a local label at the current PC location. All previous forward
7160 * references are updated to point to this location. The location is noted
7161 * for any future backward references. */
Chris Fallin91473dc2014-12-12 15:58:26 -08007162static void label(compiler *c, unsigned int label) {
Josh Habermane8ed0212015-06-08 17:56:03 -07007163 int val;
7164 uint32_t *codep;
7165
Chris Fallin91473dc2014-12-12 15:58:26 -08007166 assert(label < MAXLABEL);
Josh Habermane8ed0212015-06-08 17:56:03 -07007167 val = c->fwd_labels[label];
7168 codep = (val == EMPTYLABEL) ? NULL : c->group->bytecode + val;
Chris Fallin91473dc2014-12-12 15:58:26 -08007169 while (codep) {
7170 int ofs = getofs(*codep);
7171 setofs(codep, c->pc - codep - instruction_len(*codep));
7172 codep = ofs ? codep + ofs : NULL;
7173 }
7174 c->fwd_labels[label] = EMPTYLABEL;
7175 c->back_labels[label] = pcofs(c);
7176}
7177
Josh Habermane8ed0212015-06-08 17:56:03 -07007178/* Creates a reference to a numbered label; either a forward reference
7179 * (positive arg) or backward reference (negative arg). For forward references
7180 * the value returned now is actually a "next" pointer into a linked list of all
7181 * instructions that use this label and will be patched later when the label is
7182 * defined with label().
7183 *
7184 * The returned value is the offset that should be written into the instruction.
7185 */
Chris Fallin91473dc2014-12-12 15:58:26 -08007186static int32_t labelref(compiler *c, int label) {
7187 assert(label < MAXLABEL);
7188 if (label == LABEL_DISPATCH) {
Josh Habermane8ed0212015-06-08 17:56:03 -07007189 /* No resolving required. */
Chris Fallin91473dc2014-12-12 15:58:26 -08007190 return 0;
7191 } else if (label < 0) {
Josh Habermane8ed0212015-06-08 17:56:03 -07007192 /* Backward local label. Relative to the next instruction. */
Chris Fallin91473dc2014-12-12 15:58:26 -08007193 uint32_t from = (c->pc + 1) - c->group->bytecode;
7194 return c->back_labels[-label] - from;
7195 } else {
Josh Habermane8ed0212015-06-08 17:56:03 -07007196 /* Forward local label: prepend to (possibly-empty) linked list. */
Chris Fallin91473dc2014-12-12 15:58:26 -08007197 int *lptr = &c->fwd_labels[label];
7198 int32_t ret = (*lptr == EMPTYLABEL) ? 0 : *lptr - pcofs(c);
7199 *lptr = pcofs(c);
7200 return ret;
7201 }
7202}
7203
7204static void put32(compiler *c, uint32_t v) {
7205 mgroup *g = c->group;
7206 if (c->pc == g->bytecode_end) {
7207 int ofs = pcofs(c);
7208 size_t oldsize = g->bytecode_end - g->bytecode;
7209 size_t newsize = UPB_MAX(oldsize * 2, 64);
Josh Habermane8ed0212015-06-08 17:56:03 -07007210 /* TODO(haberman): handle OOM. */
Chris Fallin91473dc2014-12-12 15:58:26 -08007211 g->bytecode = realloc(g->bytecode, newsize * sizeof(uint32_t));
7212 g->bytecode_end = g->bytecode + newsize;
7213 c->pc = g->bytecode + ofs;
7214 }
7215 *c->pc++ = v;
7216}
7217
7218static void putop(compiler *c, opcode op, ...) {
7219 va_list ap;
7220 va_start(ap, op);
7221
7222 switch (op) {
7223 case OP_SETDISPATCH: {
7224 uintptr_t ptr = (uintptr_t)va_arg(ap, void*);
7225 put32(c, OP_SETDISPATCH);
7226 put32(c, ptr);
7227 if (sizeof(uintptr_t) > sizeof(uint32_t))
7228 put32(c, (uint64_t)ptr >> 32);
7229 break;
7230 }
7231 case OP_STARTMSG:
7232 case OP_ENDMSG:
7233 case OP_PUSHLENDELIM:
7234 case OP_POP:
7235 case OP_SETDELIM:
7236 case OP_HALT:
7237 case OP_RET:
Chris Fallin97b663a2015-01-09 16:15:22 -08007238 case OP_DISPATCH:
Chris Fallin91473dc2014-12-12 15:58:26 -08007239 put32(c, op);
7240 break;
7241 case OP_PARSE_DOUBLE:
7242 case OP_PARSE_FLOAT:
7243 case OP_PARSE_INT64:
7244 case OP_PARSE_UINT64:
7245 case OP_PARSE_INT32:
7246 case OP_PARSE_FIXED64:
7247 case OP_PARSE_FIXED32:
7248 case OP_PARSE_BOOL:
7249 case OP_PARSE_UINT32:
7250 case OP_PARSE_SFIXED32:
7251 case OP_PARSE_SFIXED64:
7252 case OP_PARSE_SINT32:
7253 case OP_PARSE_SINT64:
7254 case OP_STARTSEQ:
7255 case OP_ENDSEQ:
7256 case OP_STARTSUBMSG:
7257 case OP_ENDSUBMSG:
7258 case OP_STARTSTR:
7259 case OP_STRING:
7260 case OP_ENDSTR:
7261 case OP_PUSHTAGDELIM:
7262 put32(c, op | va_arg(ap, upb_selector_t) << 8);
7263 break;
7264 case OP_SETBIGGROUPNUM:
7265 put32(c, op);
7266 put32(c, va_arg(ap, int));
7267 break;
7268 case OP_CALL: {
7269 const upb_pbdecodermethod *method = va_arg(ap, upb_pbdecodermethod *);
7270 put32(c, op | (method->code_base.ofs - (pcofs(c) + 1)) << 8);
7271 break;
7272 }
7273 case OP_CHECKDELIM:
7274 case OP_BRANCH: {
7275 uint32_t instruction = op;
7276 int label = va_arg(ap, int);
7277 setofs(&instruction, labelref(c, label));
7278 put32(c, instruction);
7279 break;
7280 }
7281 case OP_TAG1:
7282 case OP_TAG2: {
7283 int label = va_arg(ap, int);
7284 uint64_t tag = va_arg(ap, uint64_t);
7285 uint32_t instruction = op | (tag << 16);
7286 assert(tag <= 0xffff);
7287 setofs(&instruction, labelref(c, label));
7288 put32(c, instruction);
7289 break;
7290 }
7291 case OP_TAGN: {
7292 int label = va_arg(ap, int);
7293 uint64_t tag = va_arg(ap, uint64_t);
7294 uint32_t instruction = op | (upb_value_size(tag) << 16);
7295 setofs(&instruction, labelref(c, label));
7296 put32(c, instruction);
7297 put32(c, tag);
7298 put32(c, tag >> 32);
7299 break;
7300 }
7301 }
7302
7303 va_end(ap);
7304}
7305
7306#if defined(UPB_USE_JIT_X64) || defined(UPB_DUMP_BYTECODE)
7307
7308const char *upb_pbdecoder_getopname(unsigned int op) {
Josh Habermane8ed0212015-06-08 17:56:03 -07007309#define QUOTE(x) #x
7310#define EXPAND_AND_QUOTE(x) QUOTE(x)
7311#define OPNAME(x) OP_##x
7312#define OP(x) case OPNAME(x): return EXPAND_AND_QUOTE(OPNAME(x));
7313#define T(x) OP(PARSE_##x)
7314 /* Keep in sync with list in decoder.int.h. */
7315 switch ((opcode)op) {
7316 T(DOUBLE) T(FLOAT) T(INT64) T(UINT64) T(INT32) T(FIXED64) T(FIXED32)
7317 T(BOOL) T(UINT32) T(SFIXED32) T(SFIXED64) T(SINT32) T(SINT64)
7318 OP(STARTMSG) OP(ENDMSG) OP(STARTSEQ) OP(ENDSEQ) OP(STARTSUBMSG)
7319 OP(ENDSUBMSG) OP(STARTSTR) OP(STRING) OP(ENDSTR) OP(CALL) OP(RET)
7320 OP(PUSHLENDELIM) OP(PUSHTAGDELIM) OP(SETDELIM) OP(CHECKDELIM)
7321 OP(BRANCH) OP(TAG1) OP(TAG2) OP(TAGN) OP(SETDISPATCH) OP(POP)
7322 OP(SETBIGGROUPNUM) OP(DISPATCH) OP(HALT)
7323 }
7324 return "<unknown op>";
Chris Fallin91473dc2014-12-12 15:58:26 -08007325#undef OP
7326#undef T
7327}
7328
7329#endif
7330
7331#ifdef UPB_DUMP_BYTECODE
7332
7333static void dumpbc(uint32_t *p, uint32_t *end, FILE *f) {
7334
7335 uint32_t *begin = p;
7336
7337 while (p < end) {
7338 fprintf(f, "%p %8tx", p, p - begin);
7339 uint32_t instr = *p++;
7340 uint8_t op = getop(instr);
7341 fprintf(f, " %s", upb_pbdecoder_getopname(op));
7342 switch ((opcode)op) {
7343 case OP_SETDISPATCH: {
7344 const upb_inttable *dispatch;
7345 memcpy(&dispatch, p, sizeof(void*));
7346 p += ptr_words;
7347 const upb_pbdecodermethod *method =
7348 (void *)((char *)dispatch -
7349 offsetof(upb_pbdecodermethod, dispatch));
7350 fprintf(f, " %s", upb_msgdef_fullname(
7351 upb_handlers_msgdef(method->dest_handlers_)));
7352 break;
7353 }
Chris Fallin97b663a2015-01-09 16:15:22 -08007354 case OP_DISPATCH:
Chris Fallin91473dc2014-12-12 15:58:26 -08007355 case OP_STARTMSG:
7356 case OP_ENDMSG:
7357 case OP_PUSHLENDELIM:
7358 case OP_POP:
7359 case OP_SETDELIM:
7360 case OP_HALT:
7361 case OP_RET:
7362 break;
7363 case OP_PARSE_DOUBLE:
7364 case OP_PARSE_FLOAT:
7365 case OP_PARSE_INT64:
7366 case OP_PARSE_UINT64:
7367 case OP_PARSE_INT32:
7368 case OP_PARSE_FIXED64:
7369 case OP_PARSE_FIXED32:
7370 case OP_PARSE_BOOL:
7371 case OP_PARSE_UINT32:
7372 case OP_PARSE_SFIXED32:
7373 case OP_PARSE_SFIXED64:
7374 case OP_PARSE_SINT32:
7375 case OP_PARSE_SINT64:
7376 case OP_STARTSEQ:
7377 case OP_ENDSEQ:
7378 case OP_STARTSUBMSG:
7379 case OP_ENDSUBMSG:
7380 case OP_STARTSTR:
7381 case OP_STRING:
7382 case OP_ENDSTR:
7383 case OP_PUSHTAGDELIM:
7384 fprintf(f, " %d", instr >> 8);
7385 break;
7386 case OP_SETBIGGROUPNUM:
7387 fprintf(f, " %d", *p++);
7388 break;
7389 case OP_CHECKDELIM:
7390 case OP_CALL:
7391 case OP_BRANCH:
7392 fprintf(f, " =>0x%tx", p + getofs(instr) - begin);
7393 break;
7394 case OP_TAG1:
7395 case OP_TAG2: {
7396 fprintf(f, " tag:0x%x", instr >> 16);
7397 if (getofs(instr)) {
7398 fprintf(f, " =>0x%tx", p + getofs(instr) - begin);
7399 }
7400 break;
7401 }
7402 case OP_TAGN: {
7403 uint64_t tag = *p++;
7404 tag |= (uint64_t)*p++ << 32;
7405 fprintf(f, " tag:0x%llx", (long long)tag);
7406 fprintf(f, " n:%d", instr >> 16);
7407 if (getofs(instr)) {
7408 fprintf(f, " =>0x%tx", p + getofs(instr) - begin);
7409 }
7410 break;
7411 }
7412 }
7413 fputs("\n", f);
7414 }
7415}
7416
7417#endif
7418
7419static uint64_t get_encoded_tag(const upb_fielddef *f, int wire_type) {
7420 uint32_t tag = (upb_fielddef_number(f) << 3) | wire_type;
7421 uint64_t encoded_tag = upb_vencode32(tag);
Josh Habermane8ed0212015-06-08 17:56:03 -07007422 /* No tag should be greater than 5 bytes. */
Chris Fallin91473dc2014-12-12 15:58:26 -08007423 assert(encoded_tag <= 0xffffffffff);
7424 return encoded_tag;
7425}
7426
7427static void putchecktag(compiler *c, const upb_fielddef *f,
7428 int wire_type, int dest) {
7429 uint64_t tag = get_encoded_tag(f, wire_type);
7430 switch (upb_value_size(tag)) {
7431 case 1:
7432 putop(c, OP_TAG1, dest, tag);
7433 break;
7434 case 2:
7435 putop(c, OP_TAG2, dest, tag);
7436 break;
7437 default:
7438 putop(c, OP_TAGN, dest, tag);
7439 break;
7440 }
7441}
7442
7443static upb_selector_t getsel(const upb_fielddef *f, upb_handlertype_t type) {
7444 upb_selector_t selector;
7445 bool ok = upb_handlers_getselector(f, type, &selector);
7446 UPB_ASSERT_VAR(ok, ok);
7447 return selector;
7448}
7449
Josh Habermane8ed0212015-06-08 17:56:03 -07007450/* Takes an existing, primary dispatch table entry and repacks it with a
7451 * different alternate wire type. Called when we are inserting a secondary
7452 * dispatch table entry for an alternate wire type. */
Chris Fallin91473dc2014-12-12 15:58:26 -08007453static uint64_t repack(uint64_t dispatch, int new_wt2) {
7454 uint64_t ofs;
7455 uint8_t wt1;
7456 uint8_t old_wt2;
7457 upb_pbdecoder_unpackdispatch(dispatch, &ofs, &wt1, &old_wt2);
Josh Habermane8ed0212015-06-08 17:56:03 -07007458 assert(old_wt2 == NO_WIRE_TYPE); /* wt2 should not be set yet. */
Chris Fallin91473dc2014-12-12 15:58:26 -08007459 return upb_pbdecoder_packdispatch(ofs, wt1, new_wt2);
7460}
7461
Josh Habermane8ed0212015-06-08 17:56:03 -07007462/* Marks the current bytecode position as the dispatch target for this message,
7463 * field, and wire type. */
Chris Fallin91473dc2014-12-12 15:58:26 -08007464static void dispatchtarget(compiler *c, upb_pbdecodermethod *method,
7465 const upb_fielddef *f, int wire_type) {
Josh Habermane8ed0212015-06-08 17:56:03 -07007466 /* Offset is relative to msg base. */
Chris Fallin91473dc2014-12-12 15:58:26 -08007467 uint64_t ofs = pcofs(c) - method->code_base.ofs;
7468 uint32_t fn = upb_fielddef_number(f);
7469 upb_inttable *d = &method->dispatch;
7470 upb_value v;
7471 if (upb_inttable_remove(d, fn, &v)) {
Josh Habermane8ed0212015-06-08 17:56:03 -07007472 /* TODO: prioritize based on packed setting in .proto file. */
Chris Fallin91473dc2014-12-12 15:58:26 -08007473 uint64_t repacked = repack(upb_value_getuint64(v), wire_type);
7474 upb_inttable_insert(d, fn, upb_value_uint64(repacked));
7475 upb_inttable_insert(d, fn + UPB_MAX_FIELDNUMBER, upb_value_uint64(ofs));
7476 } else {
7477 uint64_t val = upb_pbdecoder_packdispatch(ofs, wire_type, NO_WIRE_TYPE);
7478 upb_inttable_insert(d, fn, upb_value_uint64(val));
7479 }
7480}
7481
7482static void putpush(compiler *c, const upb_fielddef *f) {
7483 if (upb_fielddef_descriptortype(f) == UPB_DESCRIPTOR_TYPE_MESSAGE) {
7484 putop(c, OP_PUSHLENDELIM);
7485 } else {
7486 uint32_t fn = upb_fielddef_number(f);
7487 if (fn >= 1 << 24) {
7488 putop(c, OP_PUSHTAGDELIM, 0);
7489 putop(c, OP_SETBIGGROUPNUM, fn);
7490 } else {
7491 putop(c, OP_PUSHTAGDELIM, fn);
7492 }
7493 }
7494}
7495
7496static upb_pbdecodermethod *find_submethod(const compiler *c,
7497 const upb_pbdecodermethod *method,
7498 const upb_fielddef *f) {
7499 const upb_handlers *sub =
7500 upb_handlers_getsubhandlers(method->dest_handlers_, f);
7501 upb_value v;
7502 return upb_inttable_lookupptr(&c->group->methods, sub, &v)
7503 ? upb_value_getptr(v)
7504 : NULL;
7505}
7506
7507static void putsel(compiler *c, opcode op, upb_selector_t sel,
7508 const upb_handlers *h) {
7509 if (upb_handlers_gethandler(h, sel)) {
7510 putop(c, op, sel);
7511 }
7512}
7513
Josh Habermane8ed0212015-06-08 17:56:03 -07007514/* Puts an opcode to call a callback, but only if a callback actually exists for
7515 * this field and handler type. */
Chris Fallin91473dc2014-12-12 15:58:26 -08007516static void maybeput(compiler *c, opcode op, const upb_handlers *h,
7517 const upb_fielddef *f, upb_handlertype_t type) {
7518 putsel(c, op, getsel(f, type), h);
7519}
7520
7521static bool haslazyhandlers(const upb_handlers *h, const upb_fielddef *f) {
7522 if (!upb_fielddef_lazy(f))
7523 return false;
7524
7525 return upb_handlers_gethandler(h, getsel(f, UPB_HANDLER_STARTSTR)) ||
7526 upb_handlers_gethandler(h, getsel(f, UPB_HANDLER_STRING)) ||
7527 upb_handlers_gethandler(h, getsel(f, UPB_HANDLER_ENDSTR));
7528}
7529
7530
7531/* bytecode compiler code generation ******************************************/
7532
Josh Habermane8ed0212015-06-08 17:56:03 -07007533/* Symbolic names for our local labels. */
7534#define LABEL_LOOPSTART 1 /* Top of a repeated field loop. */
7535#define LABEL_LOOPBREAK 2 /* To jump out of a repeated loop */
7536#define LABEL_FIELD 3 /* Jump backward to find the most recent field. */
7537#define LABEL_ENDMSG 4 /* To reach the OP_ENDMSG instr for this msg. */
Chris Fallin91473dc2014-12-12 15:58:26 -08007538
Josh Habermane8ed0212015-06-08 17:56:03 -07007539/* Generates bytecode to parse a single non-lazy message field. */
Chris Fallin91473dc2014-12-12 15:58:26 -08007540static void generate_msgfield(compiler *c, const upb_fielddef *f,
7541 upb_pbdecodermethod *method) {
7542 const upb_handlers *h = upb_pbdecodermethod_desthandlers(method);
7543 const upb_pbdecodermethod *sub_m = find_submethod(c, method, f);
Josh Habermane8ed0212015-06-08 17:56:03 -07007544 int wire_type;
Chris Fallin91473dc2014-12-12 15:58:26 -08007545
7546 if (!sub_m) {
Josh Habermane8ed0212015-06-08 17:56:03 -07007547 /* Don't emit any code for this field at all; it will be parsed as an
Josh Haberman78da6662016-01-13 19:05:43 -08007548 * unknown field.
7549 *
7550 * TODO(haberman): we should change this to parse it as a string field
7551 * instead. It will probably be faster, but more importantly, once we
7552 * start vending unknown fields, a field shouldn't be treated as unknown
7553 * just because it doesn't have subhandlers registered. */
Chris Fallin91473dc2014-12-12 15:58:26 -08007554 return;
7555 }
7556
7557 label(c, LABEL_FIELD);
7558
Josh Habermane8ed0212015-06-08 17:56:03 -07007559 wire_type =
Chris Fallin91473dc2014-12-12 15:58:26 -08007560 (upb_fielddef_descriptortype(f) == UPB_DESCRIPTOR_TYPE_MESSAGE)
7561 ? UPB_WIRE_TYPE_DELIMITED
7562 : UPB_WIRE_TYPE_START_GROUP;
7563
7564 if (upb_fielddef_isseq(f)) {
7565 putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
7566 putchecktag(c, f, wire_type, LABEL_DISPATCH);
7567 dispatchtarget(c, method, f, wire_type);
7568 putop(c, OP_PUSHTAGDELIM, 0);
7569 putop(c, OP_STARTSEQ, getsel(f, UPB_HANDLER_STARTSEQ));
7570 label(c, LABEL_LOOPSTART);
7571 putpush(c, f);
7572 putop(c, OP_STARTSUBMSG, getsel(f, UPB_HANDLER_STARTSUBMSG));
7573 putop(c, OP_CALL, sub_m);
7574 putop(c, OP_POP);
7575 maybeput(c, OP_ENDSUBMSG, h, f, UPB_HANDLER_ENDSUBMSG);
7576 if (wire_type == UPB_WIRE_TYPE_DELIMITED) {
7577 putop(c, OP_SETDELIM);
7578 }
7579 putop(c, OP_CHECKDELIM, LABEL_LOOPBREAK);
7580 putchecktag(c, f, wire_type, LABEL_LOOPBREAK);
7581 putop(c, OP_BRANCH, -LABEL_LOOPSTART);
7582 label(c, LABEL_LOOPBREAK);
7583 putop(c, OP_POP);
7584 maybeput(c, OP_ENDSEQ, h, f, UPB_HANDLER_ENDSEQ);
7585 } else {
7586 putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
7587 putchecktag(c, f, wire_type, LABEL_DISPATCH);
7588 dispatchtarget(c, method, f, wire_type);
7589 putpush(c, f);
7590 putop(c, OP_STARTSUBMSG, getsel(f, UPB_HANDLER_STARTSUBMSG));
7591 putop(c, OP_CALL, sub_m);
7592 putop(c, OP_POP);
7593 maybeput(c, OP_ENDSUBMSG, h, f, UPB_HANDLER_ENDSUBMSG);
7594 if (wire_type == UPB_WIRE_TYPE_DELIMITED) {
7595 putop(c, OP_SETDELIM);
7596 }
7597 }
7598}
7599
Josh Habermane8ed0212015-06-08 17:56:03 -07007600/* Generates bytecode to parse a single string or lazy submessage field. */
Chris Fallin91473dc2014-12-12 15:58:26 -08007601static void generate_delimfield(compiler *c, const upb_fielddef *f,
7602 upb_pbdecodermethod *method) {
7603 const upb_handlers *h = upb_pbdecodermethod_desthandlers(method);
7604
7605 label(c, LABEL_FIELD);
7606 if (upb_fielddef_isseq(f)) {
7607 putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
7608 putchecktag(c, f, UPB_WIRE_TYPE_DELIMITED, LABEL_DISPATCH);
7609 dispatchtarget(c, method, f, UPB_WIRE_TYPE_DELIMITED);
7610 putop(c, OP_PUSHTAGDELIM, 0);
7611 putop(c, OP_STARTSEQ, getsel(f, UPB_HANDLER_STARTSEQ));
7612 label(c, LABEL_LOOPSTART);
7613 putop(c, OP_PUSHLENDELIM);
7614 putop(c, OP_STARTSTR, getsel(f, UPB_HANDLER_STARTSTR));
Josh Habermane8ed0212015-06-08 17:56:03 -07007615 /* Need to emit even if no handler to skip past the string. */
Chris Fallin91473dc2014-12-12 15:58:26 -08007616 putop(c, OP_STRING, getsel(f, UPB_HANDLER_STRING));
7617 putop(c, OP_POP);
7618 maybeput(c, OP_ENDSTR, h, f, UPB_HANDLER_ENDSTR);
7619 putop(c, OP_SETDELIM);
7620 putop(c, OP_CHECKDELIM, LABEL_LOOPBREAK);
7621 putchecktag(c, f, UPB_WIRE_TYPE_DELIMITED, LABEL_LOOPBREAK);
7622 putop(c, OP_BRANCH, -LABEL_LOOPSTART);
7623 label(c, LABEL_LOOPBREAK);
7624 putop(c, OP_POP);
7625 maybeput(c, OP_ENDSEQ, h, f, UPB_HANDLER_ENDSEQ);
7626 } else {
7627 putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
7628 putchecktag(c, f, UPB_WIRE_TYPE_DELIMITED, LABEL_DISPATCH);
7629 dispatchtarget(c, method, f, UPB_WIRE_TYPE_DELIMITED);
7630 putop(c, OP_PUSHLENDELIM);
7631 putop(c, OP_STARTSTR, getsel(f, UPB_HANDLER_STARTSTR));
7632 putop(c, OP_STRING, getsel(f, UPB_HANDLER_STRING));
7633 putop(c, OP_POP);
7634 maybeput(c, OP_ENDSTR, h, f, UPB_HANDLER_ENDSTR);
7635 putop(c, OP_SETDELIM);
7636 }
7637}
7638
Josh Habermane8ed0212015-06-08 17:56:03 -07007639/* Generates bytecode to parse a single primitive field. */
Chris Fallin91473dc2014-12-12 15:58:26 -08007640static void generate_primitivefield(compiler *c, const upb_fielddef *f,
7641 upb_pbdecodermethod *method) {
Chris Fallin91473dc2014-12-12 15:58:26 -08007642 const upb_handlers *h = upb_pbdecodermethod_desthandlers(method);
7643 upb_descriptortype_t descriptor_type = upb_fielddef_descriptortype(f);
Josh Habermane8ed0212015-06-08 17:56:03 -07007644 opcode parse_type;
7645 upb_selector_t sel;
7646 int wire_type;
Chris Fallin91473dc2014-12-12 15:58:26 -08007647
Josh Habermane8ed0212015-06-08 17:56:03 -07007648 label(c, LABEL_FIELD);
7649
7650 /* From a decoding perspective, ENUM is the same as INT32. */
Chris Fallin91473dc2014-12-12 15:58:26 -08007651 if (descriptor_type == UPB_DESCRIPTOR_TYPE_ENUM)
7652 descriptor_type = UPB_DESCRIPTOR_TYPE_INT32;
7653
Josh Habermane8ed0212015-06-08 17:56:03 -07007654 parse_type = (opcode)descriptor_type;
Chris Fallin91473dc2014-12-12 15:58:26 -08007655
Josh Habermane8ed0212015-06-08 17:56:03 -07007656 /* TODO(haberman): generate packed or non-packed first depending on "packed"
7657 * setting in the fielddef. This will favor (in speed) whichever was
7658 * specified. */
Chris Fallin91473dc2014-12-12 15:58:26 -08007659
7660 assert((int)parse_type >= 0 && parse_type <= OP_MAX);
Josh Habermane8ed0212015-06-08 17:56:03 -07007661 sel = getsel(f, upb_handlers_getprimitivehandlertype(f));
7662 wire_type = upb_pb_native_wire_types[upb_fielddef_descriptortype(f)];
Chris Fallin91473dc2014-12-12 15:58:26 -08007663 if (upb_fielddef_isseq(f)) {
7664 putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
7665 putchecktag(c, f, UPB_WIRE_TYPE_DELIMITED, LABEL_DISPATCH);
7666 dispatchtarget(c, method, f, UPB_WIRE_TYPE_DELIMITED);
7667 putop(c, OP_PUSHLENDELIM);
Josh Habermane8ed0212015-06-08 17:56:03 -07007668 putop(c, OP_STARTSEQ, getsel(f, UPB_HANDLER_STARTSEQ)); /* Packed */
Chris Fallin91473dc2014-12-12 15:58:26 -08007669 label(c, LABEL_LOOPSTART);
7670 putop(c, parse_type, sel);
7671 putop(c, OP_CHECKDELIM, LABEL_LOOPBREAK);
7672 putop(c, OP_BRANCH, -LABEL_LOOPSTART);
7673 dispatchtarget(c, method, f, wire_type);
7674 putop(c, OP_PUSHTAGDELIM, 0);
Josh Habermane8ed0212015-06-08 17:56:03 -07007675 putop(c, OP_STARTSEQ, getsel(f, UPB_HANDLER_STARTSEQ)); /* Non-packed */
Chris Fallin91473dc2014-12-12 15:58:26 -08007676 label(c, LABEL_LOOPSTART);
7677 putop(c, parse_type, sel);
7678 putop(c, OP_CHECKDELIM, LABEL_LOOPBREAK);
7679 putchecktag(c, f, wire_type, LABEL_LOOPBREAK);
7680 putop(c, OP_BRANCH, -LABEL_LOOPSTART);
7681 label(c, LABEL_LOOPBREAK);
Josh Habermane8ed0212015-06-08 17:56:03 -07007682 putop(c, OP_POP); /* Packed and non-packed join. */
Chris Fallin91473dc2014-12-12 15:58:26 -08007683 maybeput(c, OP_ENDSEQ, h, f, UPB_HANDLER_ENDSEQ);
Josh Habermane8ed0212015-06-08 17:56:03 -07007684 putop(c, OP_SETDELIM); /* Could remove for non-packed by dup ENDSEQ. */
Chris Fallin91473dc2014-12-12 15:58:26 -08007685 } else {
7686 putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
7687 putchecktag(c, f, wire_type, LABEL_DISPATCH);
7688 dispatchtarget(c, method, f, wire_type);
7689 putop(c, parse_type, sel);
7690 }
7691}
7692
Josh Habermane8ed0212015-06-08 17:56:03 -07007693/* Adds bytecode for parsing the given message to the given decoderplan,
7694 * while adding all dispatch targets to this message's dispatch table. */
Chris Fallin91473dc2014-12-12 15:58:26 -08007695static void compile_method(compiler *c, upb_pbdecodermethod *method) {
Josh Habermane8ed0212015-06-08 17:56:03 -07007696 const upb_handlers *h;
7697 const upb_msgdef *md;
7698 uint32_t* start_pc;
7699 upb_msg_field_iter i;
7700 upb_value val;
7701
Chris Fallin91473dc2014-12-12 15:58:26 -08007702 assert(method);
7703
Josh Habermane8ed0212015-06-08 17:56:03 -07007704 /* Clear all entries in the dispatch table. */
Chris Fallin91473dc2014-12-12 15:58:26 -08007705 upb_inttable_uninit(&method->dispatch);
7706 upb_inttable_init(&method->dispatch, UPB_CTYPE_UINT64);
7707
Josh Habermane8ed0212015-06-08 17:56:03 -07007708 h = upb_pbdecodermethod_desthandlers(method);
7709 md = upb_handlers_msgdef(h);
Chris Fallin91473dc2014-12-12 15:58:26 -08007710
7711 method->code_base.ofs = pcofs(c);
7712 putop(c, OP_SETDISPATCH, &method->dispatch);
7713 putsel(c, OP_STARTMSG, UPB_STARTMSG_SELECTOR, h);
7714 label(c, LABEL_FIELD);
Josh Habermane8ed0212015-06-08 17:56:03 -07007715 start_pc = c->pc;
Chris Fallinfcd88892015-01-13 18:14:39 -08007716 for(upb_msg_field_begin(&i, md);
7717 !upb_msg_field_done(&i);
7718 upb_msg_field_next(&i)) {
Chris Fallin91473dc2014-12-12 15:58:26 -08007719 const upb_fielddef *f = upb_msg_iter_field(&i);
7720 upb_fieldtype_t type = upb_fielddef_type(f);
7721
7722 if (type == UPB_TYPE_MESSAGE && !(haslazyhandlers(h, f) && c->lazy)) {
7723 generate_msgfield(c, f, method);
7724 } else if (type == UPB_TYPE_STRING || type == UPB_TYPE_BYTES ||
7725 type == UPB_TYPE_MESSAGE) {
7726 generate_delimfield(c, f, method);
7727 } else {
7728 generate_primitivefield(c, f, method);
7729 }
7730 }
7731
Josh Habermane8ed0212015-06-08 17:56:03 -07007732 /* If there were no fields, or if no handlers were defined, we need to
7733 * generate a non-empty loop body so that we can at least dispatch for unknown
7734 * fields and check for the end of the message. */
Chris Fallin97b663a2015-01-09 16:15:22 -08007735 if (c->pc == start_pc) {
Josh Habermane8ed0212015-06-08 17:56:03 -07007736 /* Check for end-of-message. */
Chris Fallin97b663a2015-01-09 16:15:22 -08007737 putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
Josh Habermane8ed0212015-06-08 17:56:03 -07007738 /* Unconditionally dispatch. */
Chris Fallin97b663a2015-01-09 16:15:22 -08007739 putop(c, OP_DISPATCH, 0);
7740 }
7741
Josh Habermane8ed0212015-06-08 17:56:03 -07007742 /* For now we just loop back to the last field of the message (or if none,
7743 * the DISPATCH opcode for the message). */
Chris Fallin91473dc2014-12-12 15:58:26 -08007744 putop(c, OP_BRANCH, -LABEL_FIELD);
7745
Josh Habermane8ed0212015-06-08 17:56:03 -07007746 /* Insert both a label and a dispatch table entry for this end-of-msg. */
Chris Fallin91473dc2014-12-12 15:58:26 -08007747 label(c, LABEL_ENDMSG);
Josh Habermane8ed0212015-06-08 17:56:03 -07007748 val = upb_value_uint64(pcofs(c) - method->code_base.ofs);
Chris Fallin91473dc2014-12-12 15:58:26 -08007749 upb_inttable_insert(&method->dispatch, DISPATCH_ENDMSG, val);
7750
7751 putsel(c, OP_ENDMSG, UPB_ENDMSG_SELECTOR, h);
7752 putop(c, OP_RET);
7753
7754 upb_inttable_compact(&method->dispatch);
7755}
7756
Josh Habermane8ed0212015-06-08 17:56:03 -07007757/* Populate "methods" with new upb_pbdecodermethod objects reachable from "h".
7758 * Returns the method for these handlers.
7759 *
7760 * Generates a new method for every destination handlers reachable from "h". */
Chris Fallin91473dc2014-12-12 15:58:26 -08007761static void find_methods(compiler *c, const upb_handlers *h) {
7762 upb_value v;
Josh Habermane8ed0212015-06-08 17:56:03 -07007763 upb_msg_field_iter i;
7764 const upb_msgdef *md;
7765
Chris Fallin91473dc2014-12-12 15:58:26 -08007766 if (upb_inttable_lookupptr(&c->group->methods, h, &v))
7767 return;
7768 newmethod(h, c->group);
7769
Josh Habermane8ed0212015-06-08 17:56:03 -07007770 /* Find submethods. */
7771 md = upb_handlers_msgdef(h);
Chris Fallinfcd88892015-01-13 18:14:39 -08007772 for(upb_msg_field_begin(&i, md);
7773 !upb_msg_field_done(&i);
7774 upb_msg_field_next(&i)) {
Chris Fallin91473dc2014-12-12 15:58:26 -08007775 const upb_fielddef *f = upb_msg_iter_field(&i);
7776 const upb_handlers *sub_h;
7777 if (upb_fielddef_type(f) == UPB_TYPE_MESSAGE &&
7778 (sub_h = upb_handlers_getsubhandlers(h, f)) != NULL) {
Josh Habermane8ed0212015-06-08 17:56:03 -07007779 /* We only generate a decoder method for submessages with handlers.
7780 * Others will be parsed as unknown fields. */
Chris Fallin91473dc2014-12-12 15:58:26 -08007781 find_methods(c, sub_h);
7782 }
7783 }
7784}
7785
Josh Habermane8ed0212015-06-08 17:56:03 -07007786/* (Re-)compile bytecode for all messages in "msgs."
7787 * Overwrites any existing bytecode in "c". */
Chris Fallin91473dc2014-12-12 15:58:26 -08007788static void compile_methods(compiler *c) {
Josh Habermane8ed0212015-06-08 17:56:03 -07007789 upb_inttable_iter i;
7790
7791 /* Start over at the beginning of the bytecode. */
Chris Fallin91473dc2014-12-12 15:58:26 -08007792 c->pc = c->group->bytecode;
7793
Chris Fallin91473dc2014-12-12 15:58:26 -08007794 upb_inttable_begin(&i, &c->group->methods);
7795 for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
7796 upb_pbdecodermethod *method = upb_value_getptr(upb_inttable_iter_value(&i));
7797 compile_method(c, method);
7798 }
7799}
7800
7801static void set_bytecode_handlers(mgroup *g) {
7802 upb_inttable_iter i;
7803 upb_inttable_begin(&i, &g->methods);
7804 for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
7805 upb_pbdecodermethod *m = upb_value_getptr(upb_inttable_iter_value(&i));
Josh Habermane8ed0212015-06-08 17:56:03 -07007806 upb_byteshandler *h = &m->input_handler_;
Chris Fallin91473dc2014-12-12 15:58:26 -08007807
7808 m->code_base.ptr = g->bytecode + m->code_base.ofs;
7809
Chris Fallin91473dc2014-12-12 15:58:26 -08007810 upb_byteshandler_setstartstr(h, upb_pbdecoder_startbc, m->code_base.ptr);
7811 upb_byteshandler_setstring(h, upb_pbdecoder_decode, g);
7812 upb_byteshandler_setendstr(h, upb_pbdecoder_end, m);
7813 }
7814}
7815
7816
Chris Fallinfcd88892015-01-13 18:14:39 -08007817/* JIT setup. *****************************************************************/
Chris Fallin91473dc2014-12-12 15:58:26 -08007818
7819#ifdef UPB_USE_JIT_X64
7820
7821static void sethandlers(mgroup *g, bool allowjit) {
7822 g->jit_code = NULL;
7823 if (allowjit) {
Josh Habermane8ed0212015-06-08 17:56:03 -07007824 /* Compile byte-code into machine code, create handlers. */
Chris Fallin91473dc2014-12-12 15:58:26 -08007825 upb_pbdecoder_jit(g);
7826 } else {
7827 set_bytecode_handlers(g);
7828 }
7829}
7830
Josh Habermane8ed0212015-06-08 17:56:03 -07007831#else /* UPB_USE_JIT_X64 */
Chris Fallin91473dc2014-12-12 15:58:26 -08007832
7833static void sethandlers(mgroup *g, bool allowjit) {
Josh Habermane8ed0212015-06-08 17:56:03 -07007834 /* No JIT compiled in; use bytecode handlers unconditionally. */
Chris Fallin91473dc2014-12-12 15:58:26 -08007835 UPB_UNUSED(allowjit);
7836 set_bytecode_handlers(g);
7837}
7838
Josh Habermane8ed0212015-06-08 17:56:03 -07007839#endif /* UPB_USE_JIT_X64 */
Chris Fallin91473dc2014-12-12 15:58:26 -08007840
7841
Josh Habermane8ed0212015-06-08 17:56:03 -07007842/* TODO(haberman): allow this to be constructed for an arbitrary set of dest
7843 * handlers and other mgroups (but verify we have a transitive closure). */
Chris Fallin91473dc2014-12-12 15:58:26 -08007844const mgroup *mgroup_new(const upb_handlers *dest, bool allowjit, bool lazy,
7845 const void *owner) {
Josh Habermane8ed0212015-06-08 17:56:03 -07007846 mgroup *g;
7847 compiler *c;
7848
Chris Fallin91473dc2014-12-12 15:58:26 -08007849 UPB_UNUSED(allowjit);
7850 assert(upb_handlers_isfrozen(dest));
7851
Josh Habermane8ed0212015-06-08 17:56:03 -07007852 g = newgroup(owner);
7853 c = newcompiler(g, lazy);
Chris Fallin91473dc2014-12-12 15:58:26 -08007854 find_methods(c, dest);
7855
Josh Habermane8ed0212015-06-08 17:56:03 -07007856 /* We compile in two passes:
7857 * 1. all messages are assigned relative offsets from the beginning of the
7858 * bytecode (saved in method->code_base).
7859 * 2. forwards OP_CALL instructions can be correctly linked since message
7860 * offsets have been previously assigned.
7861 *
7862 * Could avoid the second pass by linking OP_CALL instructions somehow. */
Chris Fallin91473dc2014-12-12 15:58:26 -08007863 compile_methods(c);
7864 compile_methods(c);
7865 g->bytecode_end = c->pc;
7866 freecompiler(c);
7867
7868#ifdef UPB_DUMP_BYTECODE
Josh Habermane8ed0212015-06-08 17:56:03 -07007869 {
Josh Habermanf654d492016-02-18 11:07:51 -08007870 FILE *f = fopen("/tmp/upb-bytecode", "w");
Josh Habermane8ed0212015-06-08 17:56:03 -07007871 assert(f);
7872 dumpbc(g->bytecode, g->bytecode_end, stderr);
7873 dumpbc(g->bytecode, g->bytecode_end, f);
7874 fclose(f);
Josh Habermanf654d492016-02-18 11:07:51 -08007875
7876 f = fopen("/tmp/upb-bytecode.bin", "wb");
7877 assert(f);
7878 fwrite(g->bytecode, 1, g->bytecode_end - g->bytecode, f);
7879 fclose(f);
Josh Habermane8ed0212015-06-08 17:56:03 -07007880 }
Chris Fallin91473dc2014-12-12 15:58:26 -08007881#endif
7882
7883 sethandlers(g, allowjit);
7884 return g;
7885}
7886
7887
7888/* upb_pbcodecache ************************************************************/
7889
7890void upb_pbcodecache_init(upb_pbcodecache *c) {
7891 upb_inttable_init(&c->groups, UPB_CTYPE_CONSTPTR);
7892 c->allow_jit_ = true;
7893}
7894
7895void upb_pbcodecache_uninit(upb_pbcodecache *c) {
7896 upb_inttable_iter i;
7897 upb_inttable_begin(&i, &c->groups);
7898 for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
7899 const mgroup *group = upb_value_getconstptr(upb_inttable_iter_value(&i));
Josh Habermane8ed0212015-06-08 17:56:03 -07007900 mgroup_unref(group, c);
Chris Fallin91473dc2014-12-12 15:58:26 -08007901 }
7902 upb_inttable_uninit(&c->groups);
7903}
7904
7905bool upb_pbcodecache_allowjit(const upb_pbcodecache *c) {
7906 return c->allow_jit_;
7907}
7908
7909bool upb_pbcodecache_setallowjit(upb_pbcodecache *c, bool allow) {
7910 if (upb_inttable_count(&c->groups) > 0)
7911 return false;
7912 c->allow_jit_ = allow;
7913 return true;
7914}
7915
7916const upb_pbdecodermethod *upb_pbcodecache_getdecodermethod(
7917 upb_pbcodecache *c, const upb_pbdecodermethodopts *opts) {
Josh Habermane8ed0212015-06-08 17:56:03 -07007918 upb_value v;
7919 bool ok;
7920
7921 /* Right now we build a new DecoderMethod every time.
7922 * TODO(haberman): properly cache methods by their true key. */
Chris Fallin91473dc2014-12-12 15:58:26 -08007923 const mgroup *g = mgroup_new(opts->handlers, c->allow_jit_, opts->lazy, c);
7924 upb_inttable_push(&c->groups, upb_value_constptr(g));
7925
Josh Habermane8ed0212015-06-08 17:56:03 -07007926 ok = upb_inttable_lookupptr(&g->methods, opts->handlers, &v);
Chris Fallin91473dc2014-12-12 15:58:26 -08007927 UPB_ASSERT_VAR(ok, ok);
7928 return upb_value_getptr(v);
7929}
7930
7931
7932/* upb_pbdecodermethodopts ****************************************************/
7933
7934void upb_pbdecodermethodopts_init(upb_pbdecodermethodopts *opts,
7935 const upb_handlers *h) {
7936 opts->handlers = h;
7937 opts->lazy = false;
7938}
7939
7940void upb_pbdecodermethodopts_setlazy(upb_pbdecodermethodopts *opts, bool lazy) {
7941 opts->lazy = lazy;
7942}
7943/*
Josh Haberman181c7f22015-07-15 11:05:10 -07007944** upb::Decoder (Bytecode Decoder VM)
7945**
7946** Bytecode must previously have been generated using the bytecode compiler in
7947** compile_decoder.c. This decoder then walks through the bytecode op-by-op to
7948** parse the input.
7949**
7950** Decoding is fully resumable; we just keep a pointer to the current bytecode
7951** instruction and resume from there. A fair amount of the logic here is to
7952** handle the fact that values can span buffer seams and we have to be able to
7953** be capable of suspending/resuming from any byte in the stream. This
7954** sometimes requires keeping a few trailing bytes from the last buffer around
7955** in the "residual" buffer.
7956*/
Chris Fallin91473dc2014-12-12 15:58:26 -08007957
7958#include <inttypes.h>
Chris Fallin91473dc2014-12-12 15:58:26 -08007959#include <stddef.h>
Chris Fallin91473dc2014-12-12 15:58:26 -08007960
7961#ifdef UPB_DUMP_BYTECODE
7962#include <stdio.h>
7963#endif
7964
7965#define CHECK_SUSPEND(x) if (!(x)) return upb_pbdecoder_suspend(d);
7966
Josh Habermane8ed0212015-06-08 17:56:03 -07007967/* Error messages that are shared between the bytecode and JIT decoders. */
Chris Fallin91473dc2014-12-12 15:58:26 -08007968const char *kPbDecoderStackOverflow = "Nesting too deep.";
Josh Haberman5bdf4a42015-08-03 15:51:31 -07007969const char *kPbDecoderSubmessageTooLong =
7970 "Submessage end extends past enclosing submessage.";
Chris Fallin91473dc2014-12-12 15:58:26 -08007971
Josh Habermane8ed0212015-06-08 17:56:03 -07007972/* Error messages shared within this file. */
Chris Fallin91473dc2014-12-12 15:58:26 -08007973static const char *kUnterminatedVarint = "Unterminated varint.";
7974
7975/* upb_pbdecoder **************************************************************/
7976
7977static opcode halt = OP_HALT;
7978
Josh Haberman78da6662016-01-13 19:05:43 -08007979/* A dummy character we can point to when the user passes us a NULL buffer.
7980 * We need this because in C (NULL + 0) and (NULL - NULL) are undefined
7981 * behavior, which would invalidate functions like curbufleft(). */
7982static const char dummy_char;
7983
Josh Habermane8ed0212015-06-08 17:56:03 -07007984/* Whether an op consumes any of the input buffer. */
Chris Fallin91473dc2014-12-12 15:58:26 -08007985static bool consumes_input(opcode op) {
7986 switch (op) {
7987 case OP_SETDISPATCH:
7988 case OP_STARTMSG:
7989 case OP_ENDMSG:
7990 case OP_STARTSEQ:
7991 case OP_ENDSEQ:
7992 case OP_STARTSUBMSG:
7993 case OP_ENDSUBMSG:
7994 case OP_STARTSTR:
7995 case OP_ENDSTR:
7996 case OP_PUSHTAGDELIM:
7997 case OP_POP:
7998 case OP_SETDELIM:
7999 case OP_SETBIGGROUPNUM:
8000 case OP_CHECKDELIM:
8001 case OP_CALL:
8002 case OP_RET:
8003 case OP_BRANCH:
8004 return false;
8005 default:
8006 return true;
8007 }
8008}
8009
Josh Haberman5bdf4a42015-08-03 15:51:31 -07008010static size_t stacksize(upb_pbdecoder *d, size_t entries) {
8011 UPB_UNUSED(d);
8012 return entries * sizeof(upb_pbdecoder_frame);
8013}
8014
8015static size_t callstacksize(upb_pbdecoder *d, size_t entries) {
8016 UPB_UNUSED(d);
8017
8018#ifdef UPB_USE_JIT_X64
8019 if (d->method_->is_native_) {
8020 /* Each native stack frame needs two pointers, plus we need a few frames for
8021 * the enter/exit trampolines. */
8022 size_t ret = entries * sizeof(void*) * 2;
8023 ret += sizeof(void*) * 10;
8024 return ret;
8025 }
8026#endif
8027
8028 return entries * sizeof(uint32_t*);
8029}
8030
8031
Chris Fallin91473dc2014-12-12 15:58:26 -08008032static bool in_residual_buf(const upb_pbdecoder *d, const char *p);
8033
Josh Habermane8ed0212015-06-08 17:56:03 -07008034/* It's unfortunate that we have to micro-manage the compiler with
8035 * UPB_FORCEINLINE and UPB_NOINLINE, especially since this tuning is necessarily
8036 * specific to one hardware configuration. But empirically on a Core i7,
8037 * performance increases 30-50% with these annotations. Every instance where
8038 * these appear, gcc 4.2.1 made the wrong decision and degraded performance in
8039 * benchmarks. */
Chris Fallin91473dc2014-12-12 15:58:26 -08008040
8041static void seterr(upb_pbdecoder *d, const char *msg) {
Chris Fallind3262772015-05-14 18:24:26 -07008042 upb_status status = UPB_STATUS_INIT;
8043 upb_status_seterrmsg(&status, msg);
8044 upb_env_reporterror(d->env, &status);
Chris Fallin91473dc2014-12-12 15:58:26 -08008045}
8046
8047void upb_pbdecoder_seterr(upb_pbdecoder *d, const char *msg) {
8048 seterr(d, msg);
8049}
8050
8051
8052/* Buffering ******************************************************************/
8053
Josh Habermane8ed0212015-06-08 17:56:03 -07008054/* We operate on one buffer at a time, which is either the user's buffer passed
8055 * to our "decode" callback or some residual bytes from the previous buffer. */
Chris Fallin91473dc2014-12-12 15:58:26 -08008056
Josh Habermane8ed0212015-06-08 17:56:03 -07008057/* How many bytes can be safely read from d->ptr without reading past end-of-buf
8058 * or past the current delimited end. */
Chris Fallin91473dc2014-12-12 15:58:26 -08008059static size_t curbufleft(const upb_pbdecoder *d) {
8060 assert(d->data_end >= d->ptr);
8061 return d->data_end - d->ptr;
8062}
8063
Josh Haberman5bdf4a42015-08-03 15:51:31 -07008064/* How many bytes are available before end-of-buffer. */
8065static size_t bufleft(const upb_pbdecoder *d) {
8066 return d->end - d->ptr;
8067}
8068
Josh Habermane8ed0212015-06-08 17:56:03 -07008069/* Overall stream offset of d->ptr. */
Chris Fallin91473dc2014-12-12 15:58:26 -08008070uint64_t offset(const upb_pbdecoder *d) {
8071 return d->bufstart_ofs + (d->ptr - d->buf);
8072}
8073
Josh Haberman5bdf4a42015-08-03 15:51:31 -07008074/* How many bytes are available before the end of this delimited region. */
8075size_t delim_remaining(const upb_pbdecoder *d) {
8076 return d->top->end_ofs - offset(d);
8077}
8078
Josh Habermane8ed0212015-06-08 17:56:03 -07008079/* Advances d->ptr. */
Chris Fallin91473dc2014-12-12 15:58:26 -08008080static void advance(upb_pbdecoder *d, size_t len) {
8081 assert(curbufleft(d) >= len);
8082 d->ptr += len;
8083}
8084
8085static bool in_buf(const char *p, const char *buf, const char *end) {
8086 return p >= buf && p <= end;
8087}
8088
8089static bool in_residual_buf(const upb_pbdecoder *d, const char *p) {
8090 return in_buf(p, d->residual, d->residual_end);
8091}
8092
Josh Habermane8ed0212015-06-08 17:56:03 -07008093/* Calculates the delim_end value, which is affected by both the current buffer
8094 * and the parsing stack, so must be called whenever either is updated. */
Chris Fallin91473dc2014-12-12 15:58:26 -08008095static void set_delim_end(upb_pbdecoder *d) {
8096 size_t delim_ofs = d->top->end_ofs - d->bufstart_ofs;
Chris Fallind3262772015-05-14 18:24:26 -07008097 if (delim_ofs <= (size_t)(d->end - d->buf)) {
Chris Fallin91473dc2014-12-12 15:58:26 -08008098 d->delim_end = d->buf + delim_ofs;
8099 d->data_end = d->delim_end;
8100 } else {
8101 d->data_end = d->end;
8102 d->delim_end = NULL;
8103 }
8104}
8105
8106static void switchtobuf(upb_pbdecoder *d, const char *buf, const char *end) {
8107 d->ptr = buf;
8108 d->buf = buf;
8109 d->end = end;
8110 set_delim_end(d);
8111}
8112
8113static void advancetobuf(upb_pbdecoder *d, const char *buf, size_t len) {
8114 assert(curbufleft(d) == 0);
8115 d->bufstart_ofs += (d->end - d->buf);
8116 switchtobuf(d, buf, buf + len);
8117}
8118
8119static void checkpoint(upb_pbdecoder *d) {
Josh Habermane8ed0212015-06-08 17:56:03 -07008120 /* The assertion here is in the interests of efficiency, not correctness.
8121 * We are trying to ensure that we don't checkpoint() more often than
8122 * necessary. */
Chris Fallin91473dc2014-12-12 15:58:26 -08008123 assert(d->checkpoint != d->ptr);
8124 d->checkpoint = d->ptr;
8125}
8126
Josh Haberman5bdf4a42015-08-03 15:51:31 -07008127/* Skips "bytes" bytes in the stream, which may be more than available. If we
8128 * skip more bytes than are available, we return a long read count to the caller
8129 * indicating how many bytes can be skipped over before passing actual data
8130 * again. Skipped bytes can pass a NULL buffer and the decoder guarantees they
8131 * won't actually be read.
8132 */
8133static int32_t skip(upb_pbdecoder *d, size_t bytes) {
8134 assert(!in_residual_buf(d, d->ptr) || d->size_param == 0);
8135 assert(d->skip == 0);
8136 if (bytes > delim_remaining(d)) {
8137 seterr(d, "Skipped value extended beyond enclosing submessage.");
8138 return upb_pbdecoder_suspend(d);
Josh Haberman78da6662016-01-13 19:05:43 -08008139 } else if (bufleft(d) >= bytes) {
Josh Haberman5bdf4a42015-08-03 15:51:31 -07008140 /* Skipped data is all in current buffer, and more is still available. */
8141 advance(d, bytes);
8142 d->skip = 0;
8143 return DECODE_OK;
8144 } else {
8145 /* Skipped data extends beyond currently available buffers. */
8146 d->pc = d->last;
8147 d->skip = bytes - curbufleft(d);
8148 d->bufstart_ofs += (d->end - d->buf);
8149 d->residual_end = d->residual;
8150 switchtobuf(d, d->residual, d->residual_end);
8151 return d->size_param + d->skip;
8152 }
8153}
8154
8155
Josh Habermane8ed0212015-06-08 17:56:03 -07008156/* Resumes the decoder from an initial state or from a previous suspend. */
Chris Fallin91473dc2014-12-12 15:58:26 -08008157int32_t upb_pbdecoder_resume(upb_pbdecoder *d, void *p, const char *buf,
8158 size_t size, const upb_bufhandle *handle) {
Josh Habermane8ed0212015-06-08 17:56:03 -07008159 UPB_UNUSED(p); /* Useless; just for the benefit of the JIT. */
Josh Haberman5bdf4a42015-08-03 15:51:31 -07008160
Josh Haberman78da6662016-01-13 19:05:43 -08008161 /* d->skip and d->residual_end could probably elegantly be represented
8162 * as a single variable, to more easily represent this invariant. */
8163 assert(!(d->skip && d->residual_end > d->residual));
8164
8165 /* We need to remember the original size_param, so that the value we return
8166 * is relative to it, even if we do some skipping first. */
Chris Fallin91473dc2014-12-12 15:58:26 -08008167 d->size_param = size;
8168 d->handle = handle;
Josh Haberman5bdf4a42015-08-03 15:51:31 -07008169
Josh Haberman78da6662016-01-13 19:05:43 -08008170 /* Have to handle this case specially (ie. not with skip()) because the user
8171 * is allowed to pass a NULL buffer here, which won't allow us to safely
8172 * calculate a d->end or use our normal functions like curbufleft(). */
8173 if (d->skip && d->skip >= size) {
8174 d->skip -= size;
8175 d->bufstart_ofs += size;
8176 buf = &dummy_char;
8177 size = 0;
8178
8179 /* We can't just return now, because we might need to execute some ops
8180 * like CHECKDELIM, which could call some callbacks and pop the stack. */
8181 }
8182
8183 /* We need to pretend that this was the actual buffer param, since some of the
8184 * calculations assume that d->ptr/d->buf is relative to this. */
8185 d->buf_param = buf;
8186
8187 if (!buf) {
8188 /* NULL buf is ok if its entire span is covered by the "skip" above, but
8189 * by this point we know that "skip" doesn't cover the buffer. */
8190 seterr(d, "Passed NULL buffer over non-skippable region.");
8191 return upb_pbdecoder_suspend(d);
8192 }
8193
Chris Fallin91473dc2014-12-12 15:58:26 -08008194 if (d->residual_end > d->residual) {
Josh Habermane8ed0212015-06-08 17:56:03 -07008195 /* We have residual bytes from the last buffer. */
Chris Fallin91473dc2014-12-12 15:58:26 -08008196 assert(d->ptr == d->residual);
8197 } else {
8198 switchtobuf(d, buf, buf + size);
8199 }
Josh Haberman5bdf4a42015-08-03 15:51:31 -07008200
Chris Fallin91473dc2014-12-12 15:58:26 -08008201 d->checkpoint = d->ptr;
Josh Haberman5bdf4a42015-08-03 15:51:31 -07008202
Josh Haberman78da6662016-01-13 19:05:43 -08008203 /* Handle skips that don't cover the whole buffer (as above). */
Josh Haberman5bdf4a42015-08-03 15:51:31 -07008204 if (d->skip) {
8205 size_t skip_bytes = d->skip;
8206 d->skip = 0;
8207 CHECK_RETURN(skip(d, skip_bytes));
Josh Haberman78da6662016-01-13 19:05:43 -08008208 checkpoint(d);
Josh Haberman5bdf4a42015-08-03 15:51:31 -07008209 }
8210
Josh Haberman78da6662016-01-13 19:05:43 -08008211 /* If we're inside an unknown group, continue to parse unknown values. */
Chris Fallin91473dc2014-12-12 15:58:26 -08008212 if (d->top->groupnum < 0) {
8213 CHECK_RETURN(upb_pbdecoder_skipunknown(d, -1, 0));
Josh Haberman78da6662016-01-13 19:05:43 -08008214 checkpoint(d);
Chris Fallin91473dc2014-12-12 15:58:26 -08008215 }
Josh Haberman5bdf4a42015-08-03 15:51:31 -07008216
Chris Fallin91473dc2014-12-12 15:58:26 -08008217 return DECODE_OK;
8218}
8219
Josh Habermane8ed0212015-06-08 17:56:03 -07008220/* Suspends the decoder at the last checkpoint, without saving any residual
8221 * bytes. If there are any unconsumed bytes, returns a short byte count. */
Chris Fallin91473dc2014-12-12 15:58:26 -08008222size_t upb_pbdecoder_suspend(upb_pbdecoder *d) {
8223 d->pc = d->last;
8224 if (d->checkpoint == d->residual) {
Josh Habermane8ed0212015-06-08 17:56:03 -07008225 /* Checkpoint was in residual buf; no user bytes were consumed. */
Chris Fallin91473dc2014-12-12 15:58:26 -08008226 d->ptr = d->residual;
8227 return 0;
8228 } else {
Josh Haberman78da6662016-01-13 19:05:43 -08008229 size_t ret = d->size_param - (d->end - d->checkpoint);
Chris Fallin91473dc2014-12-12 15:58:26 -08008230 assert(!in_residual_buf(d, d->checkpoint));
Josh Haberman78da6662016-01-13 19:05:43 -08008231 assert(d->buf == d->buf_param || d->buf == &dummy_char);
Josh Habermane8ed0212015-06-08 17:56:03 -07008232
Josh Haberman78da6662016-01-13 19:05:43 -08008233 d->bufstart_ofs += (d->checkpoint - d->buf);
Chris Fallin91473dc2014-12-12 15:58:26 -08008234 d->residual_end = d->residual;
8235 switchtobuf(d, d->residual, d->residual_end);
Josh Haberman78da6662016-01-13 19:05:43 -08008236 return ret;
Chris Fallin91473dc2014-12-12 15:58:26 -08008237 }
8238}
8239
Josh Habermane8ed0212015-06-08 17:56:03 -07008240/* Suspends the decoder at the last checkpoint, and saves any unconsumed
8241 * bytes in our residual buffer. This is necessary if we need more user
8242 * bytes to form a complete value, which might not be contiguous in the
8243 * user's buffers. Always consumes all user bytes. */
Chris Fallin91473dc2014-12-12 15:58:26 -08008244static size_t suspend_save(upb_pbdecoder *d) {
Josh Habermane8ed0212015-06-08 17:56:03 -07008245 /* We hit end-of-buffer before we could parse a full value.
8246 * Save any unconsumed bytes (if any) to the residual buffer. */
Chris Fallin91473dc2014-12-12 15:58:26 -08008247 d->pc = d->last;
8248
8249 if (d->checkpoint == d->residual) {
Josh Habermane8ed0212015-06-08 17:56:03 -07008250 /* Checkpoint was in residual buf; append user byte(s) to residual buf. */
Chris Fallin91473dc2014-12-12 15:58:26 -08008251 assert((d->residual_end - d->residual) + d->size_param <=
8252 sizeof(d->residual));
8253 if (!in_residual_buf(d, d->ptr)) {
8254 d->bufstart_ofs -= (d->residual_end - d->residual);
8255 }
8256 memcpy(d->residual_end, d->buf_param, d->size_param);
8257 d->residual_end += d->size_param;
8258 } else {
Josh Habermane8ed0212015-06-08 17:56:03 -07008259 /* Checkpoint was in user buf; old residual bytes not needed. */
8260 size_t save;
Chris Fallin91473dc2014-12-12 15:58:26 -08008261 assert(!in_residual_buf(d, d->checkpoint));
Josh Habermane8ed0212015-06-08 17:56:03 -07008262
Chris Fallin91473dc2014-12-12 15:58:26 -08008263 d->ptr = d->checkpoint;
Josh Habermane8ed0212015-06-08 17:56:03 -07008264 save = curbufleft(d);
Chris Fallin91473dc2014-12-12 15:58:26 -08008265 assert(save <= sizeof(d->residual));
8266 memcpy(d->residual, d->ptr, save);
8267 d->residual_end = d->residual + save;
8268 d->bufstart_ofs = offset(d);
8269 }
8270
8271 switchtobuf(d, d->residual, d->residual_end);
8272 return d->size_param;
8273}
8274
Josh Habermane8ed0212015-06-08 17:56:03 -07008275/* Copies the next "bytes" bytes into "buf" and advances the stream.
8276 * Requires that this many bytes are available in the current buffer. */
Chris Fallind3262772015-05-14 18:24:26 -07008277UPB_FORCEINLINE static void consumebytes(upb_pbdecoder *d, void *buf,
8278 size_t bytes) {
Chris Fallin91473dc2014-12-12 15:58:26 -08008279 assert(bytes <= curbufleft(d));
8280 memcpy(buf, d->ptr, bytes);
8281 advance(d, bytes);
8282}
8283
Josh Habermane8ed0212015-06-08 17:56:03 -07008284/* Slow path for getting the next "bytes" bytes, regardless of whether they are
8285 * available in the current buffer or not. Returns a status code as described
8286 * in decoder.int.h. */
Chris Fallind3262772015-05-14 18:24:26 -07008287UPB_NOINLINE static int32_t getbytes_slow(upb_pbdecoder *d, void *buf,
8288 size_t bytes) {
Chris Fallin91473dc2014-12-12 15:58:26 -08008289 const size_t avail = curbufleft(d);
8290 consumebytes(d, buf, avail);
8291 bytes -= avail;
8292 assert(bytes > 0);
8293 if (in_residual_buf(d, d->ptr)) {
8294 advancetobuf(d, d->buf_param, d->size_param);
8295 }
8296 if (curbufleft(d) >= bytes) {
Chris Fallind3262772015-05-14 18:24:26 -07008297 consumebytes(d, (char *)buf + avail, bytes);
Chris Fallin91473dc2014-12-12 15:58:26 -08008298 return DECODE_OK;
8299 } else if (d->data_end == d->delim_end) {
8300 seterr(d, "Submessage ended in the middle of a value or group");
8301 return upb_pbdecoder_suspend(d);
8302 } else {
8303 return suspend_save(d);
8304 }
8305}
8306
Josh Habermane8ed0212015-06-08 17:56:03 -07008307/* Gets the next "bytes" bytes, regardless of whether they are available in the
8308 * current buffer or not. Returns a status code as described in decoder.int.h.
8309 */
Chris Fallind3262772015-05-14 18:24:26 -07008310UPB_FORCEINLINE static int32_t getbytes(upb_pbdecoder *d, void *buf,
8311 size_t bytes) {
Chris Fallin91473dc2014-12-12 15:58:26 -08008312 if (curbufleft(d) >= bytes) {
Josh Habermane8ed0212015-06-08 17:56:03 -07008313 /* Buffer has enough data to satisfy. */
Chris Fallin91473dc2014-12-12 15:58:26 -08008314 consumebytes(d, buf, bytes);
8315 return DECODE_OK;
8316 } else {
8317 return getbytes_slow(d, buf, bytes);
8318 }
8319}
8320
Chris Fallind3262772015-05-14 18:24:26 -07008321UPB_NOINLINE static size_t peekbytes_slow(upb_pbdecoder *d, void *buf,
8322 size_t bytes) {
Chris Fallin91473dc2014-12-12 15:58:26 -08008323 size_t ret = curbufleft(d);
8324 memcpy(buf, d->ptr, ret);
8325 if (in_residual_buf(d, d->ptr)) {
8326 size_t copy = UPB_MIN(bytes - ret, d->size_param);
Chris Fallind3262772015-05-14 18:24:26 -07008327 memcpy((char *)buf + ret, d->buf_param, copy);
Chris Fallin91473dc2014-12-12 15:58:26 -08008328 ret += copy;
8329 }
8330 return ret;
8331}
8332
Chris Fallind3262772015-05-14 18:24:26 -07008333UPB_FORCEINLINE static size_t peekbytes(upb_pbdecoder *d, void *buf,
8334 size_t bytes) {
Chris Fallin91473dc2014-12-12 15:58:26 -08008335 if (curbufleft(d) >= bytes) {
8336 memcpy(buf, d->ptr, bytes);
8337 return bytes;
8338 } else {
8339 return peekbytes_slow(d, buf, bytes);
8340 }
8341}
8342
8343
8344/* Decoding of wire types *****************************************************/
8345
Josh Habermane8ed0212015-06-08 17:56:03 -07008346/* Slow path for decoding a varint from the current buffer position.
8347 * Returns a status code as described in decoder.int.h. */
Chris Fallind3262772015-05-14 18:24:26 -07008348UPB_NOINLINE int32_t upb_pbdecoder_decode_varint_slow(upb_pbdecoder *d,
8349 uint64_t *u64) {
Chris Fallin91473dc2014-12-12 15:58:26 -08008350 uint8_t byte = 0x80;
8351 int bitpos;
Josh Habermane8ed0212015-06-08 17:56:03 -07008352 *u64 = 0;
Chris Fallin91473dc2014-12-12 15:58:26 -08008353 for(bitpos = 0; bitpos < 70 && (byte & 0x80); bitpos += 7) {
Josh Haberman78da6662016-01-13 19:05:43 -08008354 CHECK_RETURN(getbytes(d, &byte, 1));
Chris Fallin91473dc2014-12-12 15:58:26 -08008355 *u64 |= (uint64_t)(byte & 0x7F) << bitpos;
8356 }
8357 if(bitpos == 70 && (byte & 0x80)) {
8358 seterr(d, kUnterminatedVarint);
8359 return upb_pbdecoder_suspend(d);
8360 }
8361 return DECODE_OK;
8362}
8363
Josh Habermane8ed0212015-06-08 17:56:03 -07008364/* Decodes a varint from the current buffer position.
8365 * Returns a status code as described in decoder.int.h. */
Chris Fallind3262772015-05-14 18:24:26 -07008366UPB_FORCEINLINE static int32_t decode_varint(upb_pbdecoder *d, uint64_t *u64) {
Chris Fallin91473dc2014-12-12 15:58:26 -08008367 if (curbufleft(d) > 0 && !(*d->ptr & 0x80)) {
8368 *u64 = *d->ptr;
8369 advance(d, 1);
8370 return DECODE_OK;
8371 } else if (curbufleft(d) >= 10) {
Josh Habermane8ed0212015-06-08 17:56:03 -07008372 /* Fast case. */
Chris Fallin91473dc2014-12-12 15:58:26 -08008373 upb_decoderet r = upb_vdecode_fast(d->ptr);
8374 if (r.p == NULL) {
8375 seterr(d, kUnterminatedVarint);
8376 return upb_pbdecoder_suspend(d);
8377 }
8378 advance(d, r.p - d->ptr);
8379 *u64 = r.val;
8380 return DECODE_OK;
8381 } else {
Josh Habermane8ed0212015-06-08 17:56:03 -07008382 /* Slow case -- varint spans buffer seam. */
Chris Fallin91473dc2014-12-12 15:58:26 -08008383 return upb_pbdecoder_decode_varint_slow(d, u64);
8384 }
8385}
8386
Josh Habermane8ed0212015-06-08 17:56:03 -07008387/* Decodes a 32-bit varint from the current buffer position.
8388 * Returns a status code as described in decoder.int.h. */
Chris Fallind3262772015-05-14 18:24:26 -07008389UPB_FORCEINLINE static int32_t decode_v32(upb_pbdecoder *d, uint32_t *u32) {
Chris Fallin91473dc2014-12-12 15:58:26 -08008390 uint64_t u64;
8391 int32_t ret = decode_varint(d, &u64);
8392 if (ret >= 0) return ret;
8393 if (u64 > UINT32_MAX) {
8394 seterr(d, "Unterminated 32-bit varint");
Josh Habermane8ed0212015-06-08 17:56:03 -07008395 /* TODO(haberman) guarantee that this function return is >= 0 somehow,
8396 * so we know this path will always be treated as error by our caller.
8397 * Right now the size_t -> int32_t can overflow and produce negative values.
8398 */
Chris Fallin91473dc2014-12-12 15:58:26 -08008399 *u32 = 0;
8400 return upb_pbdecoder_suspend(d);
8401 }
8402 *u32 = u64;
8403 return DECODE_OK;
8404}
8405
Josh Habermane8ed0212015-06-08 17:56:03 -07008406/* Decodes a fixed32 from the current buffer position.
8407 * Returns a status code as described in decoder.int.h.
8408 * TODO: proper byte swapping for big-endian machines. */
Chris Fallind3262772015-05-14 18:24:26 -07008409UPB_FORCEINLINE static int32_t decode_fixed32(upb_pbdecoder *d, uint32_t *u32) {
Chris Fallin91473dc2014-12-12 15:58:26 -08008410 return getbytes(d, u32, 4);
8411}
8412
Josh Habermane8ed0212015-06-08 17:56:03 -07008413/* Decodes a fixed64 from the current buffer position.
8414 * Returns a status code as described in decoder.int.h.
8415 * TODO: proper byte swapping for big-endian machines. */
Chris Fallind3262772015-05-14 18:24:26 -07008416UPB_FORCEINLINE static int32_t decode_fixed64(upb_pbdecoder *d, uint64_t *u64) {
Chris Fallin91473dc2014-12-12 15:58:26 -08008417 return getbytes(d, u64, 8);
8418}
8419
Josh Habermane8ed0212015-06-08 17:56:03 -07008420/* Non-static versions of the above functions.
8421 * These are called by the JIT for fallback paths. */
Chris Fallin91473dc2014-12-12 15:58:26 -08008422int32_t upb_pbdecoder_decode_f32(upb_pbdecoder *d, uint32_t *u32) {
8423 return decode_fixed32(d, u32);
8424}
8425
8426int32_t upb_pbdecoder_decode_f64(upb_pbdecoder *d, uint64_t *u64) {
8427 return decode_fixed64(d, u64);
8428}
8429
8430static double as_double(uint64_t n) { double d; memcpy(&d, &n, 8); return d; }
8431static float as_float(uint32_t n) { float f; memcpy(&f, &n, 4); return f; }
8432
Josh Habermane8ed0212015-06-08 17:56:03 -07008433/* Pushes a frame onto the decoder stack. */
Chris Fallin91473dc2014-12-12 15:58:26 -08008434static bool decoder_push(upb_pbdecoder *d, uint64_t end) {
8435 upb_pbdecoder_frame *fr = d->top;
8436
8437 if (end > fr->end_ofs) {
Josh Haberman5bdf4a42015-08-03 15:51:31 -07008438 seterr(d, kPbDecoderSubmessageTooLong);
Chris Fallin91473dc2014-12-12 15:58:26 -08008439 return false;
Chris Fallind3262772015-05-14 18:24:26 -07008440 } else if (fr == d->limit) {
Chris Fallin91473dc2014-12-12 15:58:26 -08008441 seterr(d, kPbDecoderStackOverflow);
8442 return false;
8443 }
8444
8445 fr++;
8446 fr->end_ofs = end;
8447 fr->dispatch = NULL;
8448 fr->groupnum = 0;
8449 d->top = fr;
8450 return true;
8451}
8452
8453static bool pushtagdelim(upb_pbdecoder *d, uint32_t arg) {
Josh Habermane8ed0212015-06-08 17:56:03 -07008454 /* While we expect to see an "end" tag (either ENDGROUP or a non-sequence
8455 * field number) prior to hitting any enclosing submessage end, pushing our
8456 * existing delim end prevents us from continuing to parse values from a
8457 * corrupt proto that doesn't give us an END tag in time. */
Chris Fallin91473dc2014-12-12 15:58:26 -08008458 if (!decoder_push(d, d->top->end_ofs))
8459 return false;
8460 d->top->groupnum = arg;
8461 return true;
8462}
8463
Josh Habermane8ed0212015-06-08 17:56:03 -07008464/* Pops a frame from the decoder stack. */
Chris Fallin91473dc2014-12-12 15:58:26 -08008465static void decoder_pop(upb_pbdecoder *d) { d->top--; }
8466
Chris Fallind3262772015-05-14 18:24:26 -07008467UPB_NOINLINE int32_t upb_pbdecoder_checktag_slow(upb_pbdecoder *d,
8468 uint64_t expected) {
Chris Fallin91473dc2014-12-12 15:58:26 -08008469 uint64_t data = 0;
8470 size_t bytes = upb_value_size(expected);
8471 size_t read = peekbytes(d, &data, bytes);
8472 if (read == bytes && data == expected) {
Josh Habermane8ed0212015-06-08 17:56:03 -07008473 /* Advance past matched bytes. */
Chris Fallin91473dc2014-12-12 15:58:26 -08008474 int32_t ok = getbytes(d, &data, read);
8475 UPB_ASSERT_VAR(ok, ok < 0);
8476 return DECODE_OK;
8477 } else if (read < bytes && memcmp(&data, &expected, read) == 0) {
8478 return suspend_save(d);
8479 } else {
8480 return DECODE_MISMATCH;
8481 }
8482}
8483
8484int32_t upb_pbdecoder_skipunknown(upb_pbdecoder *d, int32_t fieldnum,
8485 uint8_t wire_type) {
8486 if (fieldnum >= 0)
8487 goto have_tag;
8488
8489 while (true) {
8490 uint32_t tag;
8491 CHECK_RETURN(decode_v32(d, &tag));
8492 wire_type = tag & 0x7;
8493 fieldnum = tag >> 3;
8494
8495have_tag:
8496 if (fieldnum == 0) {
8497 seterr(d, "Saw invalid field number (0)");
8498 return upb_pbdecoder_suspend(d);
8499 }
8500
Josh Habermane8ed0212015-06-08 17:56:03 -07008501 /* TODO: deliver to unknown field callback. */
Chris Fallin91473dc2014-12-12 15:58:26 -08008502 switch (wire_type) {
8503 case UPB_WIRE_TYPE_32BIT:
8504 CHECK_RETURN(skip(d, 4));
8505 break;
8506 case UPB_WIRE_TYPE_64BIT:
8507 CHECK_RETURN(skip(d, 8));
8508 break;
8509 case UPB_WIRE_TYPE_VARINT: {
8510 uint64_t u64;
8511 CHECK_RETURN(decode_varint(d, &u64));
8512 break;
8513 }
8514 case UPB_WIRE_TYPE_DELIMITED: {
8515 uint32_t len;
8516 CHECK_RETURN(decode_v32(d, &len));
8517 CHECK_RETURN(skip(d, len));
8518 break;
8519 }
8520 case UPB_WIRE_TYPE_START_GROUP:
8521 CHECK_SUSPEND(pushtagdelim(d, -fieldnum));
8522 break;
8523 case UPB_WIRE_TYPE_END_GROUP:
8524 if (fieldnum == -d->top->groupnum) {
8525 decoder_pop(d);
8526 } else if (fieldnum == d->top->groupnum) {
8527 return DECODE_ENDGROUP;
8528 } else {
8529 seterr(d, "Unmatched ENDGROUP tag.");
8530 return upb_pbdecoder_suspend(d);
8531 }
8532 break;
8533 default:
8534 seterr(d, "Invalid wire type");
8535 return upb_pbdecoder_suspend(d);
8536 }
8537
8538 if (d->top->groupnum >= 0) {
8539 return DECODE_OK;
8540 }
8541
Josh Haberman5bdf4a42015-08-03 15:51:31 -07008542 /* Unknown group -- continue looping over unknown fields. */
Chris Fallin91473dc2014-12-12 15:58:26 -08008543 checkpoint(d);
8544 }
8545}
8546
8547static void goto_endmsg(upb_pbdecoder *d) {
8548 upb_value v;
8549 bool found = upb_inttable_lookup32(d->top->dispatch, DISPATCH_ENDMSG, &v);
8550 UPB_ASSERT_VAR(found, found);
8551 d->pc = d->top->base + upb_value_getuint64(v);
8552}
8553
Josh Habermane8ed0212015-06-08 17:56:03 -07008554/* Parses a tag and jumps to the corresponding bytecode instruction for this
8555 * field.
8556 *
8557 * If the tag is unknown (or the wire type doesn't match), parses the field as
8558 * unknown. If the tag is a valid ENDGROUP tag, jumps to the bytecode
8559 * instruction for the end of message. */
Chris Fallin91473dc2014-12-12 15:58:26 -08008560static int32_t dispatch(upb_pbdecoder *d) {
8561 upb_inttable *dispatch = d->top->dispatch;
Chris Fallin91473dc2014-12-12 15:58:26 -08008562 uint32_t tag;
Josh Habermane8ed0212015-06-08 17:56:03 -07008563 uint8_t wire_type;
8564 uint32_t fieldnum;
Chris Fallin91473dc2014-12-12 15:58:26 -08008565 upb_value val;
Josh Haberman5bdf4a42015-08-03 15:51:31 -07008566 int32_t retval;
Josh Habermane8ed0212015-06-08 17:56:03 -07008567
8568 /* Decode tag. */
8569 CHECK_RETURN(decode_v32(d, &tag));
8570 wire_type = tag & 0x7;
8571 fieldnum = tag >> 3;
8572
8573 /* Lookup tag. Because of packed/non-packed compatibility, we have to
8574 * check the wire type against two possibilities. */
Chris Fallin91473dc2014-12-12 15:58:26 -08008575 if (fieldnum != DISPATCH_ENDMSG &&
8576 upb_inttable_lookup32(dispatch, fieldnum, &val)) {
8577 uint64_t v = upb_value_getuint64(val);
8578 if (wire_type == (v & 0xff)) {
8579 d->pc = d->top->base + (v >> 16);
8580 return DECODE_OK;
8581 } else if (wire_type == ((v >> 8) & 0xff)) {
8582 bool found =
8583 upb_inttable_lookup(dispatch, fieldnum + UPB_MAX_FIELDNUMBER, &val);
8584 UPB_ASSERT_VAR(found, found);
8585 d->pc = d->top->base + upb_value_getuint64(val);
8586 return DECODE_OK;
8587 }
8588 }
8589
Josh Haberman5bdf4a42015-08-03 15:51:31 -07008590 /* We have some unknown fields (or ENDGROUP) to parse. The DISPATCH or TAG
8591 * bytecode that triggered this is preceded by a CHECKDELIM bytecode which
8592 * we need to back up to, so that when we're done skipping unknown data we
8593 * can re-check the delimited end. */
8594 d->last--; /* Necessary if we get suspended */
8595 d->pc = d->last;
8596 assert(getop(*d->last) == OP_CHECKDELIM);
Chris Fallin91473dc2014-12-12 15:58:26 -08008597
Josh Haberman5bdf4a42015-08-03 15:51:31 -07008598 /* Unknown field or ENDGROUP. */
8599 retval = upb_pbdecoder_skipunknown(d, fieldnum, wire_type);
8600
8601 CHECK_RETURN(retval);
8602
8603 if (retval == DECODE_ENDGROUP) {
Chris Fallin91473dc2014-12-12 15:58:26 -08008604 goto_endmsg(d);
8605 return DECODE_OK;
Chris Fallin91473dc2014-12-12 15:58:26 -08008606 }
Chris Fallind3262772015-05-14 18:24:26 -07008607
Josh Haberman5bdf4a42015-08-03 15:51:31 -07008608 return DECODE_OK;
Chris Fallin91473dc2014-12-12 15:58:26 -08008609}
8610
Josh Habermane8ed0212015-06-08 17:56:03 -07008611/* Callers know that the stack is more than one deep because the opcodes that
8612 * call this only occur after PUSH operations. */
Chris Fallin91473dc2014-12-12 15:58:26 -08008613upb_pbdecoder_frame *outer_frame(upb_pbdecoder *d) {
8614 assert(d->top != d->stack);
8615 return d->top - 1;
8616}
8617
8618
8619/* The main decoding loop *****************************************************/
8620
Josh Habermane8ed0212015-06-08 17:56:03 -07008621/* The main decoder VM function. Uses traditional bytecode dispatch loop with a
8622 * switch() statement. */
Josh Haberman5bdf4a42015-08-03 15:51:31 -07008623size_t run_decoder_vm(upb_pbdecoder *d, const mgroup *group,
8624 const upb_bufhandle* handle) {
Chris Fallin91473dc2014-12-12 15:58:26 -08008625
8626#define VMCASE(op, code) \
8627 case op: { code; if (consumes_input(op)) checkpoint(d); break; }
8628#define PRIMITIVE_OP(type, wt, name, convfunc, ctype) \
8629 VMCASE(OP_PARSE_ ## type, { \
8630 ctype val; \
8631 CHECK_RETURN(decode_ ## wt(d, &val)); \
8632 upb_sink_put ## name(&d->top->sink, arg, (convfunc)(val)); \
8633 })
8634
8635 while(1) {
Josh Habermane8ed0212015-06-08 17:56:03 -07008636 int32_t instruction;
8637 opcode op;
8638 uint32_t arg;
8639 int32_t longofs;
8640
Chris Fallin91473dc2014-12-12 15:58:26 -08008641 d->last = d->pc;
Josh Habermane8ed0212015-06-08 17:56:03 -07008642 instruction = *d->pc++;
8643 op = getop(instruction);
8644 arg = instruction >> 8;
8645 longofs = arg;
Chris Fallin91473dc2014-12-12 15:58:26 -08008646 assert(d->ptr != d->residual_end);
Josh Haberman5bdf4a42015-08-03 15:51:31 -07008647 UPB_UNUSED(group);
Chris Fallin91473dc2014-12-12 15:58:26 -08008648#ifdef UPB_DUMP_BYTECODE
8649 fprintf(stderr, "s_ofs=%d buf_ofs=%d data_rem=%d buf_rem=%d delim_rem=%d "
8650 "%x %s (%d)\n",
8651 (int)offset(d),
8652 (int)(d->ptr - d->buf),
8653 (int)(d->data_end - d->ptr),
8654 (int)(d->end - d->ptr),
8655 (int)((d->top->end_ofs - d->bufstart_ofs) - (d->ptr - d->buf)),
8656 (int)(d->pc - 1 - group->bytecode),
8657 upb_pbdecoder_getopname(op),
8658 arg);
8659#endif
8660 switch (op) {
Josh Habermane8ed0212015-06-08 17:56:03 -07008661 /* Technically, we are losing data if we see a 32-bit varint that is not
8662 * properly sign-extended. We could detect this and error about the data
8663 * loss, but proto2 does not do this, so we pass. */
Chris Fallin91473dc2014-12-12 15:58:26 -08008664 PRIMITIVE_OP(INT32, varint, int32, int32_t, uint64_t)
8665 PRIMITIVE_OP(INT64, varint, int64, int64_t, uint64_t)
8666 PRIMITIVE_OP(UINT32, varint, uint32, uint32_t, uint64_t)
8667 PRIMITIVE_OP(UINT64, varint, uint64, uint64_t, uint64_t)
8668 PRIMITIVE_OP(FIXED32, fixed32, uint32, uint32_t, uint32_t)
8669 PRIMITIVE_OP(FIXED64, fixed64, uint64, uint64_t, uint64_t)
8670 PRIMITIVE_OP(SFIXED32, fixed32, int32, int32_t, uint32_t)
8671 PRIMITIVE_OP(SFIXED64, fixed64, int64, int64_t, uint64_t)
8672 PRIMITIVE_OP(BOOL, varint, bool, bool, uint64_t)
8673 PRIMITIVE_OP(DOUBLE, fixed64, double, as_double, uint64_t)
8674 PRIMITIVE_OP(FLOAT, fixed32, float, as_float, uint32_t)
8675 PRIMITIVE_OP(SINT32, varint, int32, upb_zzdec_32, uint64_t)
8676 PRIMITIVE_OP(SINT64, varint, int64, upb_zzdec_64, uint64_t)
8677
8678 VMCASE(OP_SETDISPATCH,
8679 d->top->base = d->pc - 1;
8680 memcpy(&d->top->dispatch, d->pc, sizeof(void*));
8681 d->pc += sizeof(void*) / sizeof(uint32_t);
8682 )
8683 VMCASE(OP_STARTMSG,
8684 CHECK_SUSPEND(upb_sink_startmsg(&d->top->sink));
8685 )
8686 VMCASE(OP_ENDMSG,
8687 CHECK_SUSPEND(upb_sink_endmsg(&d->top->sink, d->status));
8688 )
8689 VMCASE(OP_STARTSEQ,
8690 upb_pbdecoder_frame *outer = outer_frame(d);
8691 CHECK_SUSPEND(upb_sink_startseq(&outer->sink, arg, &d->top->sink));
8692 )
8693 VMCASE(OP_ENDSEQ,
8694 CHECK_SUSPEND(upb_sink_endseq(&d->top->sink, arg));
8695 )
8696 VMCASE(OP_STARTSUBMSG,
8697 upb_pbdecoder_frame *outer = outer_frame(d);
8698 CHECK_SUSPEND(upb_sink_startsubmsg(&outer->sink, arg, &d->top->sink));
8699 )
8700 VMCASE(OP_ENDSUBMSG,
8701 CHECK_SUSPEND(upb_sink_endsubmsg(&d->top->sink, arg));
8702 )
8703 VMCASE(OP_STARTSTR,
Josh Haberman5bdf4a42015-08-03 15:51:31 -07008704 uint32_t len = delim_remaining(d);
Chris Fallin91473dc2014-12-12 15:58:26 -08008705 upb_pbdecoder_frame *outer = outer_frame(d);
8706 CHECK_SUSPEND(upb_sink_startstr(&outer->sink, arg, len, &d->top->sink));
8707 if (len == 0) {
Josh Habermane8ed0212015-06-08 17:56:03 -07008708 d->pc++; /* Skip OP_STRING. */
Chris Fallin91473dc2014-12-12 15:58:26 -08008709 }
8710 )
8711 VMCASE(OP_STRING,
8712 uint32_t len = curbufleft(d);
8713 size_t n = upb_sink_putstring(&d->top->sink, arg, d->ptr, len, handle);
8714 if (n > len) {
Josh Haberman5bdf4a42015-08-03 15:51:31 -07008715 if (n > delim_remaining(d)) {
Chris Fallin91473dc2014-12-12 15:58:26 -08008716 seterr(d, "Tried to skip past end of string.");
8717 return upb_pbdecoder_suspend(d);
8718 } else {
8719 int32_t ret = skip(d, n);
Josh Habermane8ed0212015-06-08 17:56:03 -07008720 /* This shouldn't return DECODE_OK, because n > len. */
Chris Fallin91473dc2014-12-12 15:58:26 -08008721 assert(ret >= 0);
8722 return ret;
8723 }
8724 }
8725 advance(d, n);
8726 if (n < len || d->delim_end == NULL) {
Josh Habermane8ed0212015-06-08 17:56:03 -07008727 /* We aren't finished with this string yet. */
8728 d->pc--; /* Repeat OP_STRING. */
Chris Fallin91473dc2014-12-12 15:58:26 -08008729 if (n > 0) checkpoint(d);
8730 return upb_pbdecoder_suspend(d);
8731 }
8732 )
8733 VMCASE(OP_ENDSTR,
8734 CHECK_SUSPEND(upb_sink_endstr(&d->top->sink, arg));
8735 )
8736 VMCASE(OP_PUSHTAGDELIM,
8737 CHECK_SUSPEND(pushtagdelim(d, arg));
8738 )
8739 VMCASE(OP_SETBIGGROUPNUM,
8740 d->top->groupnum = *d->pc++;
8741 )
8742 VMCASE(OP_POP,
8743 assert(d->top > d->stack);
8744 decoder_pop(d);
8745 )
8746 VMCASE(OP_PUSHLENDELIM,
8747 uint32_t len;
8748 CHECK_RETURN(decode_v32(d, &len));
8749 CHECK_SUSPEND(decoder_push(d, offset(d) + len));
8750 set_delim_end(d);
8751 )
8752 VMCASE(OP_SETDELIM,
8753 set_delim_end(d);
8754 )
8755 VMCASE(OP_CHECKDELIM,
Josh Habermane8ed0212015-06-08 17:56:03 -07008756 /* We are guaranteed of this assert because we never allow ourselves to
8757 * consume bytes beyond data_end, which covers delim_end when non-NULL.
8758 */
Chris Fallin91473dc2014-12-12 15:58:26 -08008759 assert(!(d->delim_end && d->ptr > d->delim_end));
8760 if (d->ptr == d->delim_end)
8761 d->pc += longofs;
8762 )
8763 VMCASE(OP_CALL,
8764 d->callstack[d->call_len++] = d->pc;
8765 d->pc += longofs;
8766 )
8767 VMCASE(OP_RET,
8768 assert(d->call_len > 0);
8769 d->pc = d->callstack[--d->call_len];
8770 )
8771 VMCASE(OP_BRANCH,
8772 d->pc += longofs;
8773 )
8774 VMCASE(OP_TAG1,
Josh Habermane8ed0212015-06-08 17:56:03 -07008775 uint8_t expected;
Chris Fallin91473dc2014-12-12 15:58:26 -08008776 CHECK_SUSPEND(curbufleft(d) > 0);
Josh Habermane8ed0212015-06-08 17:56:03 -07008777 expected = (arg >> 8) & 0xff;
Chris Fallin91473dc2014-12-12 15:58:26 -08008778 if (*d->ptr == expected) {
8779 advance(d, 1);
8780 } else {
8781 int8_t shortofs;
8782 badtag:
8783 shortofs = arg;
8784 if (shortofs == LABEL_DISPATCH) {
8785 CHECK_RETURN(dispatch(d));
8786 } else {
8787 d->pc += shortofs;
Josh Habermane8ed0212015-06-08 17:56:03 -07008788 break; /* Avoid checkpoint(). */
Chris Fallin91473dc2014-12-12 15:58:26 -08008789 }
8790 }
8791 )
8792 VMCASE(OP_TAG2,
Josh Habermane8ed0212015-06-08 17:56:03 -07008793 uint16_t expected;
Chris Fallin91473dc2014-12-12 15:58:26 -08008794 CHECK_SUSPEND(curbufleft(d) > 0);
Josh Habermane8ed0212015-06-08 17:56:03 -07008795 expected = (arg >> 8) & 0xffff;
Chris Fallin91473dc2014-12-12 15:58:26 -08008796 if (curbufleft(d) >= 2) {
8797 uint16_t actual;
8798 memcpy(&actual, d->ptr, 2);
8799 if (expected == actual) {
8800 advance(d, 2);
8801 } else {
8802 goto badtag;
8803 }
8804 } else {
8805 int32_t result = upb_pbdecoder_checktag_slow(d, expected);
8806 if (result == DECODE_MISMATCH) goto badtag;
8807 if (result >= 0) return result;
8808 }
8809 )
8810 VMCASE(OP_TAGN, {
8811 uint64_t expected;
Josh Habermane8ed0212015-06-08 17:56:03 -07008812 int32_t result;
Chris Fallin91473dc2014-12-12 15:58:26 -08008813 memcpy(&expected, d->pc, 8);
8814 d->pc += 2;
Josh Habermane8ed0212015-06-08 17:56:03 -07008815 result = upb_pbdecoder_checktag_slow(d, expected);
Chris Fallin91473dc2014-12-12 15:58:26 -08008816 if (result == DECODE_MISMATCH) goto badtag;
8817 if (result >= 0) return result;
8818 })
Chris Fallin97b663a2015-01-09 16:15:22 -08008819 VMCASE(OP_DISPATCH, {
8820 CHECK_RETURN(dispatch(d));
8821 })
Chris Fallin91473dc2014-12-12 15:58:26 -08008822 VMCASE(OP_HALT, {
Josh Haberman5bdf4a42015-08-03 15:51:31 -07008823 return d->size_param;
Chris Fallin91473dc2014-12-12 15:58:26 -08008824 })
8825 }
8826 }
8827}
8828
Josh Haberman5bdf4a42015-08-03 15:51:31 -07008829
8830/* BytesHandler handlers ******************************************************/
8831
Chris Fallin91473dc2014-12-12 15:58:26 -08008832void *upb_pbdecoder_startbc(void *closure, const void *pc, size_t size_hint) {
8833 upb_pbdecoder *d = closure;
8834 UPB_UNUSED(size_hint);
Chris Fallind3262772015-05-14 18:24:26 -07008835 d->top->end_ofs = UINT64_MAX;
8836 d->bufstart_ofs = 0;
Chris Fallin91473dc2014-12-12 15:58:26 -08008837 d->call_len = 1;
Chris Fallind3262772015-05-14 18:24:26 -07008838 d->callstack[0] = &halt;
Chris Fallin91473dc2014-12-12 15:58:26 -08008839 d->pc = pc;
Josh Haberman5bdf4a42015-08-03 15:51:31 -07008840 d->skip = 0;
Chris Fallin91473dc2014-12-12 15:58:26 -08008841 return d;
8842}
8843
8844void *upb_pbdecoder_startjit(void *closure, const void *hd, size_t size_hint) {
Josh Habermane8ed0212015-06-08 17:56:03 -07008845 upb_pbdecoder *d = closure;
Chris Fallin91473dc2014-12-12 15:58:26 -08008846 UPB_UNUSED(hd);
8847 UPB_UNUSED(size_hint);
Chris Fallind3262772015-05-14 18:24:26 -07008848 d->top->end_ofs = UINT64_MAX;
8849 d->bufstart_ofs = 0;
Chris Fallin91473dc2014-12-12 15:58:26 -08008850 d->call_len = 0;
Josh Haberman5bdf4a42015-08-03 15:51:31 -07008851 d->skip = 0;
Chris Fallin91473dc2014-12-12 15:58:26 -08008852 return d;
8853}
8854
8855bool upb_pbdecoder_end(void *closure, const void *handler_data) {
8856 upb_pbdecoder *d = closure;
8857 const upb_pbdecodermethod *method = handler_data;
Josh Habermane8ed0212015-06-08 17:56:03 -07008858 uint64_t end;
8859 char dummy;
Chris Fallin91473dc2014-12-12 15:58:26 -08008860
8861 if (d->residual_end > d->residual) {
Josh Haberman5bdf4a42015-08-03 15:51:31 -07008862 seterr(d, "Unexpected EOF: decoder still has buffered unparsed data");
8863 return false;
8864 }
8865
8866 if (d->skip) {
8867 seterr(d, "Unexpected EOF inside skipped data");
Chris Fallin91473dc2014-12-12 15:58:26 -08008868 return false;
8869 }
8870
8871 if (d->top->end_ofs != UINT64_MAX) {
8872 seterr(d, "Unexpected EOF inside delimited string");
8873 return false;
8874 }
8875
Josh Haberman5bdf4a42015-08-03 15:51:31 -07008876 /* The user's end() call indicates that the message ends here. */
Josh Habermane8ed0212015-06-08 17:56:03 -07008877 end = offset(d);
Chris Fallin91473dc2014-12-12 15:58:26 -08008878 d->top->end_ofs = end;
8879
Chris Fallin91473dc2014-12-12 15:58:26 -08008880#ifdef UPB_USE_JIT_X64
Josh Haberman5bdf4a42015-08-03 15:51:31 -07008881 if (method->is_native_) {
8882 const mgroup *group = (const mgroup*)method->group;
Chris Fallin91473dc2014-12-12 15:58:26 -08008883 if (d->top != d->stack)
8884 d->stack->end_ofs = 0;
8885 group->jit_code(closure, method->code_base.ptr, &dummy, 0, NULL);
Josh Habermane8ed0212015-06-08 17:56:03 -07008886 } else
Chris Fallin91473dc2014-12-12 15:58:26 -08008887#endif
Josh Habermane8ed0212015-06-08 17:56:03 -07008888 {
Chris Fallin91473dc2014-12-12 15:58:26 -08008889 const uint32_t *p = d->pc;
Josh Habermane8ed0212015-06-08 17:56:03 -07008890 d->stack->end_ofs = end;
8891 /* Check the previous bytecode, but guard against beginning. */
Chris Fallin91473dc2014-12-12 15:58:26 -08008892 if (p != method->code_base.ptr) p--;
8893 if (getop(*p) == OP_CHECKDELIM) {
Josh Habermane8ed0212015-06-08 17:56:03 -07008894 /* Rewind from OP_TAG* to OP_CHECKDELIM. */
Chris Fallin91473dc2014-12-12 15:58:26 -08008895 assert(getop(*d->pc) == OP_TAG1 ||
8896 getop(*d->pc) == OP_TAG2 ||
Chris Fallin97b663a2015-01-09 16:15:22 -08008897 getop(*d->pc) == OP_TAGN ||
Josh Habermane8ed0212015-06-08 17:56:03 -07008898 getop(*d->pc) == OP_DISPATCH);
Chris Fallin91473dc2014-12-12 15:58:26 -08008899 d->pc = p;
8900 }
8901 upb_pbdecoder_decode(closure, handler_data, &dummy, 0, NULL);
Chris Fallin91473dc2014-12-12 15:58:26 -08008902 }
Chris Fallin91473dc2014-12-12 15:58:26 -08008903
8904 if (d->call_len != 0) {
Josh Haberman5bdf4a42015-08-03 15:51:31 -07008905 seterr(d, "Unexpected EOF inside submessage or group");
Chris Fallin91473dc2014-12-12 15:58:26 -08008906 return false;
8907 }
8908
8909 return true;
8910}
8911
Josh Haberman5bdf4a42015-08-03 15:51:31 -07008912size_t upb_pbdecoder_decode(void *decoder, const void *group, const char *buf,
8913 size_t size, const upb_bufhandle *handle) {
8914 int32_t result = upb_pbdecoder_resume(decoder, NULL, buf, size, handle);
8915
8916 if (result == DECODE_ENDGROUP) goto_endmsg(decoder);
8917 CHECK_RETURN(result);
8918
8919 return run_decoder_vm(decoder, group, handle);
8920}
8921
8922
8923/* Public API *****************************************************************/
8924
Chris Fallin91473dc2014-12-12 15:58:26 -08008925void upb_pbdecoder_reset(upb_pbdecoder *d) {
8926 d->top = d->stack;
Chris Fallin91473dc2014-12-12 15:58:26 -08008927 d->top->groupnum = 0;
Chris Fallin91473dc2014-12-12 15:58:26 -08008928 d->ptr = d->residual;
8929 d->buf = d->residual;
8930 d->end = d->residual;
8931 d->residual_end = d->residual;
Chris Fallind3262772015-05-14 18:24:26 -07008932}
8933
Chris Fallind3262772015-05-14 18:24:26 -07008934upb_pbdecoder *upb_pbdecoder_create(upb_env *e, const upb_pbdecodermethod *m,
8935 upb_sink *sink) {
8936 const size_t default_max_nesting = 64;
8937#ifndef NDEBUG
8938 size_t size_before = upb_env_bytesallocated(e);
8939#endif
8940
8941 upb_pbdecoder *d = upb_env_malloc(e, sizeof(upb_pbdecoder));
8942 if (!d) return NULL;
8943
8944 d->method_ = m;
8945 d->callstack = upb_env_malloc(e, callstacksize(d, default_max_nesting));
8946 d->stack = upb_env_malloc(e, stacksize(d, default_max_nesting));
8947 if (!d->stack || !d->callstack) {
8948 return NULL;
8949 }
8950
8951 d->env = e;
8952 d->limit = d->stack + default_max_nesting - 1;
8953 d->stack_size = default_max_nesting;
Josh Haberman78da6662016-01-13 19:05:43 -08008954 d->status = NULL;
Chris Fallind3262772015-05-14 18:24:26 -07008955
8956 upb_pbdecoder_reset(d);
8957 upb_bytessink_reset(&d->input_, &m->input_handler_, d);
8958
8959 assert(sink);
8960 if (d->method_->dest_handlers_) {
8961 if (sink->handlers != d->method_->dest_handlers_)
8962 return NULL;
8963 }
8964 upb_sink_reset(&d->top->sink, sink->handlers, sink->closure);
8965
Josh Habermane8ed0212015-06-08 17:56:03 -07008966 /* If this fails, increase the value in decoder.h. */
Chris Fallind3262772015-05-14 18:24:26 -07008967 assert(upb_env_bytesallocated(e) - size_before <= UPB_PB_DECODER_SIZE);
8968 return d;
Chris Fallin91473dc2014-12-12 15:58:26 -08008969}
8970
8971uint64_t upb_pbdecoder_bytesparsed(const upb_pbdecoder *d) {
8972 return offset(d);
8973}
8974
Chris Fallin91473dc2014-12-12 15:58:26 -08008975const upb_pbdecodermethod *upb_pbdecoder_method(const upb_pbdecoder *d) {
8976 return d->method_;
8977}
8978
Chris Fallin91473dc2014-12-12 15:58:26 -08008979upb_bytessink *upb_pbdecoder_input(upb_pbdecoder *d) {
8980 return &d->input_;
8981}
Chris Fallind3262772015-05-14 18:24:26 -07008982
8983size_t upb_pbdecoder_maxnesting(const upb_pbdecoder *d) {
8984 return d->stack_size;
8985}
8986
8987bool upb_pbdecoder_setmaxnesting(upb_pbdecoder *d, size_t max) {
8988 assert(d->top >= d->stack);
8989
8990 if (max < (size_t)(d->top - d->stack)) {
Josh Habermane8ed0212015-06-08 17:56:03 -07008991 /* Can't set a limit smaller than what we are currently at. */
Chris Fallind3262772015-05-14 18:24:26 -07008992 return false;
8993 }
8994
8995 if (max > d->stack_size) {
Josh Habermane8ed0212015-06-08 17:56:03 -07008996 /* Need to reallocate stack and callstack to accommodate. */
Chris Fallind3262772015-05-14 18:24:26 -07008997 size_t old_size = stacksize(d, d->stack_size);
8998 size_t new_size = stacksize(d, max);
8999 void *p = upb_env_realloc(d->env, d->stack, old_size, new_size);
9000 if (!p) {
9001 return false;
9002 }
9003 d->stack = p;
9004
9005 old_size = callstacksize(d, d->stack_size);
9006 new_size = callstacksize(d, max);
9007 p = upb_env_realloc(d->env, d->callstack, old_size, new_size);
9008 if (!p) {
9009 return false;
9010 }
9011 d->callstack = p;
9012
9013 d->stack_size = max;
9014 }
9015
9016 d->limit = d->stack + max - 1;
9017 return true;
9018}
Chris Fallin91473dc2014-12-12 15:58:26 -08009019/*
Josh Haberman181c7f22015-07-15 11:05:10 -07009020** upb::Encoder
9021**
9022** Since we are implementing pure handlers (ie. without any out-of-band access
9023** to pre-computed lengths), we have to buffer all submessages before we can
9024** emit even their first byte.
9025**
9026** Not knowing the size of submessages also means we can't write a perfect
9027** zero-copy implementation, even with buffering. Lengths are stored as
9028** varints, which means that we don't know how many bytes to reserve for the
9029** length until we know what the length is.
9030**
9031** This leaves us with three main choices:
9032**
9033** 1. buffer all submessage data in a temporary buffer, then copy it exactly
9034** once into the output buffer.
9035**
9036** 2. attempt to buffer data directly into the output buffer, estimating how
9037** many bytes each length will take. When our guesses are wrong, use
9038** memmove() to grow or shrink the allotted space.
9039**
9040** 3. buffer directly into the output buffer, allocating a max length
9041** ahead-of-time for each submessage length. If we overallocated, we waste
9042** space, but no memcpy() or memmove() is required. This approach requires
9043** defining a maximum size for submessages and rejecting submessages that
9044** exceed that size.
9045**
9046** (2) and (3) have the potential to have better performance, but they are more
9047** complicated and subtle to implement:
9048**
9049** (3) requires making an arbitrary choice of the maximum message size; it
9050** wastes space when submessages are shorter than this and fails
9051** completely when they are longer. This makes it more finicky and
9052** requires configuration based on the input. It also makes it impossible
9053** to perfectly match the output of reference encoders that always use the
9054** optimal amount of space for each length.
9055**
Josh Habermanf654d492016-02-18 11:07:51 -08009056** (2) requires guessing the the size upfront, and if multiple lengths are
Josh Haberman181c7f22015-07-15 11:05:10 -07009057** guessed wrong the minimum required number of memmove() operations may
9058** be complicated to compute correctly. Implemented properly, it may have
9059** a useful amortized or average cost, but more investigation is required
9060** to determine this and what the optimal algorithm is to achieve it.
9061**
9062** (1) makes you always pay for exactly one copy, but its implementation is
9063** the simplest and its performance is predictable.
9064**
9065** So for now, we implement (1) only. If we wish to optimize later, we should
9066** be able to do it without affecting users.
9067**
9068** The strategy is to buffer the segments of data that do *not* depend on
9069** unknown lengths in one buffer, and keep a separate buffer of segment pointers
9070** and lengths. When the top-level submessage ends, we can go beginning to end,
9071** alternating the writing of lengths with memcpy() of the rest of the data.
9072** At the top level though, no buffering is required.
9073*/
Chris Fallin91473dc2014-12-12 15:58:26 -08009074
9075
9076#include <stdlib.h>
9077
Josh Habermane8ed0212015-06-08 17:56:03 -07009078/* The output buffer is divided into segments; a segment is a string of data
9079 * that is "ready to go" -- it does not need any varint lengths inserted into
9080 * the middle. The seams between segments are where varints will be inserted
9081 * once they are known.
9082 *
9083 * We also use the concept of a "run", which is a range of encoded bytes that
9084 * occur at a single submessage level. Every segment contains one or more runs.
9085 *
9086 * A segment can span messages. Consider:
9087 *
9088 * .--Submessage lengths---------.
9089 * | | |
9090 * | V V
9091 * V | |--------------- | |-----------------
9092 * Submessages: | |-----------------------------------------------
9093 * Top-level msg: ------------------------------------------------------------
9094 *
9095 * Segments: ----- ------------------- -----------------
9096 * Runs: *---- *--------------*--- *----------------
9097 * (* marks the start)
9098 *
9099 * Note that the top-level menssage is not in any segment because it does not
9100 * have any length preceding it.
9101 *
9102 * A segment is only interrupted when another length needs to be inserted. So
9103 * observe how the second segment spans both the inner submessage and part of
9104 * the next enclosing message. */
Chris Fallind3262772015-05-14 18:24:26 -07009105typedef struct {
Josh Habermane8ed0212015-06-08 17:56:03 -07009106 uint32_t msglen; /* The length to varint-encode before this segment. */
9107 uint32_t seglen; /* Length of the segment. */
Chris Fallind3262772015-05-14 18:24:26 -07009108} upb_pb_encoder_segment;
9109
9110struct upb_pb_encoder {
9111 upb_env *env;
9112
Josh Habermane8ed0212015-06-08 17:56:03 -07009113 /* Our input and output. */
Chris Fallind3262772015-05-14 18:24:26 -07009114 upb_sink input_;
9115 upb_bytessink *output_;
9116
Josh Habermane8ed0212015-06-08 17:56:03 -07009117 /* The "subclosure" -- used as the inner closure as part of the bytessink
9118 * protocol. */
Chris Fallind3262772015-05-14 18:24:26 -07009119 void *subc;
9120
Josh Habermane8ed0212015-06-08 17:56:03 -07009121 /* The output buffer and limit, and our current write position. "buf"
9122 * initially points to "initbuf", but is dynamically allocated if we need to
9123 * grow beyond the initial size. */
Chris Fallind3262772015-05-14 18:24:26 -07009124 char *buf, *ptr, *limit;
9125
Josh Habermane8ed0212015-06-08 17:56:03 -07009126 /* The beginning of the current run, or undefined if we are at the top
9127 * level. */
Chris Fallind3262772015-05-14 18:24:26 -07009128 char *runbegin;
9129
Josh Habermane8ed0212015-06-08 17:56:03 -07009130 /* The list of segments we are accumulating. */
Chris Fallind3262772015-05-14 18:24:26 -07009131 upb_pb_encoder_segment *segbuf, *segptr, *seglimit;
9132
Josh Habermane8ed0212015-06-08 17:56:03 -07009133 /* The stack of enclosing submessages. Each entry in the stack points to the
9134 * segment where this submessage's length is being accumulated. */
Chris Fallind3262772015-05-14 18:24:26 -07009135 int *stack, *top, *stacklimit;
9136
Josh Habermane8ed0212015-06-08 17:56:03 -07009137 /* Depth of startmsg/endmsg calls. */
Chris Fallind3262772015-05-14 18:24:26 -07009138 int depth;
9139};
9140
Chris Fallin91473dc2014-12-12 15:58:26 -08009141/* low-level buffering ********************************************************/
9142
Josh Habermane8ed0212015-06-08 17:56:03 -07009143/* Low-level functions for interacting with the output buffer. */
Chris Fallin91473dc2014-12-12 15:58:26 -08009144
Josh Habermane8ed0212015-06-08 17:56:03 -07009145/* TODO(haberman): handle pushback */
Chris Fallin91473dc2014-12-12 15:58:26 -08009146static void putbuf(upb_pb_encoder *e, const char *buf, size_t len) {
9147 size_t n = upb_bytessink_putbuf(e->output_, e->subc, buf, len, NULL);
9148 UPB_ASSERT_VAR(n, n == len);
9149}
9150
9151static upb_pb_encoder_segment *top(upb_pb_encoder *e) {
9152 return &e->segbuf[*e->top];
9153}
9154
Josh Habermane8ed0212015-06-08 17:56:03 -07009155/* Call to ensure that at least "bytes" bytes are available for writing at
9156 * e->ptr. Returns false if the bytes could not be allocated. */
Chris Fallin91473dc2014-12-12 15:58:26 -08009157static bool reserve(upb_pb_encoder *e, size_t bytes) {
Chris Fallind3262772015-05-14 18:24:26 -07009158 if ((size_t)(e->limit - e->ptr) < bytes) {
Josh Habermane8ed0212015-06-08 17:56:03 -07009159 /* Grow buffer. */
9160 char *new_buf;
Chris Fallin91473dc2014-12-12 15:58:26 -08009161 size_t needed = bytes + (e->ptr - e->buf);
9162 size_t old_size = e->limit - e->buf;
Chris Fallind3262772015-05-14 18:24:26 -07009163
Chris Fallin91473dc2014-12-12 15:58:26 -08009164 size_t new_size = old_size;
Chris Fallind3262772015-05-14 18:24:26 -07009165
Chris Fallin91473dc2014-12-12 15:58:26 -08009166 while (new_size < needed) {
9167 new_size *= 2;
9168 }
9169
Josh Habermane8ed0212015-06-08 17:56:03 -07009170 new_buf = upb_env_realloc(e->env, e->buf, old_size, new_size);
Chris Fallin91473dc2014-12-12 15:58:26 -08009171
9172 if (new_buf == NULL) {
9173 return false;
9174 }
9175
Chris Fallin91473dc2014-12-12 15:58:26 -08009176 e->ptr = new_buf + (e->ptr - e->buf);
9177 e->runbegin = new_buf + (e->runbegin - e->buf);
9178 e->limit = new_buf + new_size;
9179 e->buf = new_buf;
9180 }
9181
9182 return true;
9183}
9184
Josh Habermane8ed0212015-06-08 17:56:03 -07009185/* Call when "bytes" bytes have been writte at e->ptr. The caller *must* have
9186 * previously called reserve() with at least this many bytes. */
Chris Fallin91473dc2014-12-12 15:58:26 -08009187static void encoder_advance(upb_pb_encoder *e, size_t bytes) {
Chris Fallind3262772015-05-14 18:24:26 -07009188 assert((size_t)(e->limit - e->ptr) >= bytes);
Chris Fallin91473dc2014-12-12 15:58:26 -08009189 e->ptr += bytes;
9190}
9191
Josh Habermane8ed0212015-06-08 17:56:03 -07009192/* Call when all of the bytes for a handler have been written. Flushes the
9193 * bytes if possible and necessary, returning false if this failed. */
Chris Fallin91473dc2014-12-12 15:58:26 -08009194static bool commit(upb_pb_encoder *e) {
9195 if (!e->top) {
Josh Habermane8ed0212015-06-08 17:56:03 -07009196 /* We aren't inside a delimited region. Flush our accumulated bytes to
9197 * the output.
9198 *
9199 * TODO(haberman): in the future we may want to delay flushing for
9200 * efficiency reasons. */
Chris Fallin91473dc2014-12-12 15:58:26 -08009201 putbuf(e, e->buf, e->ptr - e->buf);
9202 e->ptr = e->buf;
9203 }
9204
9205 return true;
9206}
9207
Josh Habermane8ed0212015-06-08 17:56:03 -07009208/* Writes the given bytes to the buffer, handling reserve/advance. */
Chris Fallin91473dc2014-12-12 15:58:26 -08009209static bool encode_bytes(upb_pb_encoder *e, const void *data, size_t len) {
9210 if (!reserve(e, len)) {
9211 return false;
9212 }
9213
9214 memcpy(e->ptr, data, len);
9215 encoder_advance(e, len);
9216 return true;
9217}
9218
Josh Habermane8ed0212015-06-08 17:56:03 -07009219/* Finish the current run by adding the run totals to the segment and message
9220 * length. */
Chris Fallin91473dc2014-12-12 15:58:26 -08009221static void accumulate(upb_pb_encoder *e) {
Josh Habermane8ed0212015-06-08 17:56:03 -07009222 size_t run_len;
Chris Fallin91473dc2014-12-12 15:58:26 -08009223 assert(e->ptr >= e->runbegin);
Josh Habermane8ed0212015-06-08 17:56:03 -07009224 run_len = e->ptr - e->runbegin;
Chris Fallin91473dc2014-12-12 15:58:26 -08009225 e->segptr->seglen += run_len;
9226 top(e)->msglen += run_len;
9227 e->runbegin = e->ptr;
9228}
9229
Josh Habermane8ed0212015-06-08 17:56:03 -07009230/* Call to indicate the start of delimited region for which the full length is
9231 * not yet known. All data will be buffered until the length is known.
9232 * Delimited regions may be nested; their lengths will all be tracked properly. */
Chris Fallin91473dc2014-12-12 15:58:26 -08009233static bool start_delim(upb_pb_encoder *e) {
9234 if (e->top) {
Josh Habermane8ed0212015-06-08 17:56:03 -07009235 /* We are already buffering, advance to the next segment and push it on the
9236 * stack. */
Chris Fallin91473dc2014-12-12 15:58:26 -08009237 accumulate(e);
9238
9239 if (++e->top == e->stacklimit) {
Josh Habermane8ed0212015-06-08 17:56:03 -07009240 /* TODO(haberman): grow stack? */
Chris Fallin91473dc2014-12-12 15:58:26 -08009241 return false;
9242 }
9243
9244 if (++e->segptr == e->seglimit) {
Josh Habermane8ed0212015-06-08 17:56:03 -07009245 /* Grow segment buffer. */
Chris Fallin91473dc2014-12-12 15:58:26 -08009246 size_t old_size =
9247 (e->seglimit - e->segbuf) * sizeof(upb_pb_encoder_segment);
9248 size_t new_size = old_size * 2;
Chris Fallind3262772015-05-14 18:24:26 -07009249 upb_pb_encoder_segment *new_buf =
9250 upb_env_realloc(e->env, e->segbuf, old_size, new_size);
Chris Fallin91473dc2014-12-12 15:58:26 -08009251
9252 if (new_buf == NULL) {
9253 return false;
9254 }
9255
Chris Fallin91473dc2014-12-12 15:58:26 -08009256 e->segptr = new_buf + (e->segptr - e->segbuf);
9257 e->seglimit = new_buf + (new_size / sizeof(upb_pb_encoder_segment));
9258 e->segbuf = new_buf;
9259 }
9260 } else {
Josh Habermane8ed0212015-06-08 17:56:03 -07009261 /* We were previously at the top level, start buffering. */
Chris Fallin91473dc2014-12-12 15:58:26 -08009262 e->segptr = e->segbuf;
9263 e->top = e->stack;
9264 e->runbegin = e->ptr;
9265 }
9266
9267 *e->top = e->segptr - e->segbuf;
9268 e->segptr->seglen = 0;
9269 e->segptr->msglen = 0;
9270
9271 return true;
9272}
9273
Josh Habermane8ed0212015-06-08 17:56:03 -07009274/* Call to indicate the end of a delimited region. We now know the length of
9275 * the delimited region. If we are not nested inside any other delimited
9276 * regions, we can now emit all of the buffered data we accumulated. */
Chris Fallin91473dc2014-12-12 15:58:26 -08009277static bool end_delim(upb_pb_encoder *e) {
Josh Habermane8ed0212015-06-08 17:56:03 -07009278 size_t msglen;
Chris Fallin91473dc2014-12-12 15:58:26 -08009279 accumulate(e);
Josh Habermane8ed0212015-06-08 17:56:03 -07009280 msglen = top(e)->msglen;
Chris Fallin91473dc2014-12-12 15:58:26 -08009281
9282 if (e->top == e->stack) {
Josh Habermane8ed0212015-06-08 17:56:03 -07009283 /* All lengths are now available, emit all buffered data. */
Chris Fallin91473dc2014-12-12 15:58:26 -08009284 char buf[UPB_PB_VARINT_MAX_LEN];
9285 upb_pb_encoder_segment *s;
9286 const char *ptr = e->buf;
9287 for (s = e->segbuf; s <= e->segptr; s++) {
9288 size_t lenbytes = upb_vencode64(s->msglen, buf);
9289 putbuf(e, buf, lenbytes);
9290 putbuf(e, ptr, s->seglen);
9291 ptr += s->seglen;
9292 }
9293
9294 e->ptr = e->buf;
9295 e->top = NULL;
9296 } else {
Josh Habermane8ed0212015-06-08 17:56:03 -07009297 /* Need to keep buffering; propagate length info into enclosing
9298 * submessages. */
Chris Fallin91473dc2014-12-12 15:58:26 -08009299 --e->top;
9300 top(e)->msglen += msglen + upb_varint_size(msglen);
9301 }
9302
9303 return true;
9304}
9305
9306
9307/* tag_t **********************************************************************/
9308
Josh Habermane8ed0212015-06-08 17:56:03 -07009309/* A precomputed (pre-encoded) tag and length. */
Chris Fallin91473dc2014-12-12 15:58:26 -08009310
9311typedef struct {
9312 uint8_t bytes;
9313 char tag[7];
9314} tag_t;
9315
Josh Habermane8ed0212015-06-08 17:56:03 -07009316/* Allocates a new tag for this field, and sets it in these handlerattr. */
Chris Fallin91473dc2014-12-12 15:58:26 -08009317static void new_tag(upb_handlers *h, const upb_fielddef *f, upb_wiretype_t wt,
9318 upb_handlerattr *attr) {
9319 uint32_t n = upb_fielddef_number(f);
9320
9321 tag_t *tag = malloc(sizeof(tag_t));
9322 tag->bytes = upb_vencode64((n << 3) | wt, tag->tag);
9323
9324 upb_handlerattr_init(attr);
9325 upb_handlerattr_sethandlerdata(attr, tag);
9326 upb_handlers_addcleanup(h, tag, free);
9327}
9328
9329static bool encode_tag(upb_pb_encoder *e, const tag_t *tag) {
9330 return encode_bytes(e, tag->tag, tag->bytes);
9331}
9332
9333
9334/* encoding of wire types *****************************************************/
9335
9336static bool encode_fixed64(upb_pb_encoder *e, uint64_t val) {
Josh Habermane8ed0212015-06-08 17:56:03 -07009337 /* TODO(haberman): byte-swap for big endian. */
Chris Fallin91473dc2014-12-12 15:58:26 -08009338 return encode_bytes(e, &val, sizeof(uint64_t));
9339}
9340
9341static bool encode_fixed32(upb_pb_encoder *e, uint32_t val) {
Josh Habermane8ed0212015-06-08 17:56:03 -07009342 /* TODO(haberman): byte-swap for big endian. */
Chris Fallin91473dc2014-12-12 15:58:26 -08009343 return encode_bytes(e, &val, sizeof(uint32_t));
9344}
9345
9346static bool encode_varint(upb_pb_encoder *e, uint64_t val) {
9347 if (!reserve(e, UPB_PB_VARINT_MAX_LEN)) {
9348 return false;
9349 }
9350
9351 encoder_advance(e, upb_vencode64(val, e->ptr));
9352 return true;
9353}
9354
9355static uint64_t dbl2uint64(double d) {
9356 uint64_t ret;
9357 memcpy(&ret, &d, sizeof(uint64_t));
9358 return ret;
9359}
9360
9361static uint32_t flt2uint32(float d) {
9362 uint32_t ret;
9363 memcpy(&ret, &d, sizeof(uint32_t));
9364 return ret;
9365}
9366
9367
9368/* encoding of proto types ****************************************************/
9369
9370static bool startmsg(void *c, const void *hd) {
9371 upb_pb_encoder *e = c;
9372 UPB_UNUSED(hd);
9373 if (e->depth++ == 0) {
9374 upb_bytessink_start(e->output_, 0, &e->subc);
9375 }
9376 return true;
9377}
9378
9379static bool endmsg(void *c, const void *hd, upb_status *status) {
9380 upb_pb_encoder *e = c;
9381 UPB_UNUSED(hd);
9382 UPB_UNUSED(status);
9383 if (--e->depth == 0) {
9384 upb_bytessink_end(e->output_);
9385 }
9386 return true;
9387}
9388
9389static void *encode_startdelimfield(void *c, const void *hd) {
9390 bool ok = encode_tag(c, hd) && commit(c) && start_delim(c);
9391 return ok ? c : UPB_BREAK;
9392}
9393
9394static bool encode_enddelimfield(void *c, const void *hd) {
9395 UPB_UNUSED(hd);
9396 return end_delim(c);
9397}
9398
9399static void *encode_startgroup(void *c, const void *hd) {
9400 return (encode_tag(c, hd) && commit(c)) ? c : UPB_BREAK;
9401}
9402
9403static bool encode_endgroup(void *c, const void *hd) {
9404 return encode_tag(c, hd) && commit(c);
9405}
9406
9407static void *encode_startstr(void *c, const void *hd, size_t size_hint) {
9408 UPB_UNUSED(size_hint);
9409 return encode_startdelimfield(c, hd);
9410}
9411
9412static size_t encode_strbuf(void *c, const void *hd, const char *buf,
9413 size_t len, const upb_bufhandle *h) {
9414 UPB_UNUSED(hd);
9415 UPB_UNUSED(h);
9416 return encode_bytes(c, buf, len) ? len : 0;
9417}
9418
9419#define T(type, ctype, convert, encode) \
9420 static bool encode_scalar_##type(void *e, const void *hd, ctype val) { \
9421 return encode_tag(e, hd) && encode(e, (convert)(val)) && commit(e); \
9422 } \
9423 static bool encode_packed_##type(void *e, const void *hd, ctype val) { \
9424 UPB_UNUSED(hd); \
9425 return encode(e, (convert)(val)); \
9426 }
9427
9428T(double, double, dbl2uint64, encode_fixed64)
Josh Habermane8ed0212015-06-08 17:56:03 -07009429T(float, float, flt2uint32, encode_fixed32)
9430T(int64, int64_t, uint64_t, encode_varint)
9431T(int32, int32_t, uint32_t, encode_varint)
9432T(fixed64, uint64_t, uint64_t, encode_fixed64)
9433T(fixed32, uint32_t, uint32_t, encode_fixed32)
9434T(bool, bool, bool, encode_varint)
9435T(uint32, uint32_t, uint32_t, encode_varint)
9436T(uint64, uint64_t, uint64_t, encode_varint)
9437T(enum, int32_t, uint32_t, encode_varint)
9438T(sfixed32, int32_t, uint32_t, encode_fixed32)
9439T(sfixed64, int64_t, uint64_t, encode_fixed64)
9440T(sint32, int32_t, upb_zzenc_32, encode_varint)
9441T(sint64, int64_t, upb_zzenc_64, encode_varint)
Chris Fallin91473dc2014-12-12 15:58:26 -08009442
9443#undef T
9444
9445
9446/* code to build the handlers *************************************************/
9447
9448static void newhandlers_callback(const void *closure, upb_handlers *h) {
Josh Habermane8ed0212015-06-08 17:56:03 -07009449 const upb_msgdef *m;
9450 upb_msg_field_iter i;
9451
Chris Fallin91473dc2014-12-12 15:58:26 -08009452 UPB_UNUSED(closure);
9453
9454 upb_handlers_setstartmsg(h, startmsg, NULL);
9455 upb_handlers_setendmsg(h, endmsg, NULL);
9456
Josh Habermane8ed0212015-06-08 17:56:03 -07009457 m = upb_handlers_msgdef(h);
Chris Fallinfcd88892015-01-13 18:14:39 -08009458 for(upb_msg_field_begin(&i, m);
9459 !upb_msg_field_done(&i);
9460 upb_msg_field_next(&i)) {
Chris Fallin91473dc2014-12-12 15:58:26 -08009461 const upb_fielddef *f = upb_msg_iter_field(&i);
9462 bool packed = upb_fielddef_isseq(f) && upb_fielddef_isprimitive(f) &&
9463 upb_fielddef_packed(f);
9464 upb_handlerattr attr;
9465 upb_wiretype_t wt =
9466 packed ? UPB_WIRE_TYPE_DELIMITED
9467 : upb_pb_native_wire_types[upb_fielddef_descriptortype(f)];
9468
Josh Habermane8ed0212015-06-08 17:56:03 -07009469 /* Pre-encode the tag for this field. */
Chris Fallin91473dc2014-12-12 15:58:26 -08009470 new_tag(h, f, wt, &attr);
9471
9472 if (packed) {
9473 upb_handlers_setstartseq(h, f, encode_startdelimfield, &attr);
9474 upb_handlers_setendseq(h, f, encode_enddelimfield, &attr);
9475 }
9476
9477#define T(upper, lower, upbtype) \
9478 case UPB_DESCRIPTOR_TYPE_##upper: \
9479 if (packed) { \
9480 upb_handlers_set##upbtype(h, f, encode_packed_##lower, &attr); \
9481 } else { \
9482 upb_handlers_set##upbtype(h, f, encode_scalar_##lower, &attr); \
9483 } \
9484 break;
9485
9486 switch (upb_fielddef_descriptortype(f)) {
9487 T(DOUBLE, double, double);
9488 T(FLOAT, float, float);
9489 T(INT64, int64, int64);
9490 T(INT32, int32, int32);
9491 T(FIXED64, fixed64, uint64);
9492 T(FIXED32, fixed32, uint32);
9493 T(BOOL, bool, bool);
9494 T(UINT32, uint32, uint32);
9495 T(UINT64, uint64, uint64);
9496 T(ENUM, enum, int32);
9497 T(SFIXED32, sfixed32, int32);
9498 T(SFIXED64, sfixed64, int64);
9499 T(SINT32, sint32, int32);
9500 T(SINT64, sint64, int64);
9501 case UPB_DESCRIPTOR_TYPE_STRING:
9502 case UPB_DESCRIPTOR_TYPE_BYTES:
9503 upb_handlers_setstartstr(h, f, encode_startstr, &attr);
9504 upb_handlers_setendstr(h, f, encode_enddelimfield, &attr);
9505 upb_handlers_setstring(h, f, encode_strbuf, &attr);
9506 break;
9507 case UPB_DESCRIPTOR_TYPE_MESSAGE:
9508 upb_handlers_setstartsubmsg(h, f, encode_startdelimfield, &attr);
9509 upb_handlers_setendsubmsg(h, f, encode_enddelimfield, &attr);
9510 break;
9511 case UPB_DESCRIPTOR_TYPE_GROUP: {
Josh Habermane8ed0212015-06-08 17:56:03 -07009512 /* Endgroup takes a different tag (wire_type = END_GROUP). */
Chris Fallin91473dc2014-12-12 15:58:26 -08009513 upb_handlerattr attr2;
9514 new_tag(h, f, UPB_WIRE_TYPE_END_GROUP, &attr2);
9515
9516 upb_handlers_setstartsubmsg(h, f, encode_startgroup, &attr);
9517 upb_handlers_setendsubmsg(h, f, encode_endgroup, &attr2);
9518
9519 upb_handlerattr_uninit(&attr2);
9520 break;
9521 }
9522 }
9523
9524#undef T
9525
9526 upb_handlerattr_uninit(&attr);
9527 }
9528}
9529
Chris Fallind3262772015-05-14 18:24:26 -07009530void upb_pb_encoder_reset(upb_pb_encoder *e) {
9531 e->segptr = NULL;
9532 e->top = NULL;
9533 e->depth = 0;
9534}
9535
Chris Fallin91473dc2014-12-12 15:58:26 -08009536
9537/* public API *****************************************************************/
9538
9539const upb_handlers *upb_pb_encoder_newhandlers(const upb_msgdef *m,
9540 const void *owner) {
9541 return upb_handlers_newfrozen(m, owner, newhandlers_callback, NULL);
9542}
9543
Chris Fallind3262772015-05-14 18:24:26 -07009544upb_pb_encoder *upb_pb_encoder_create(upb_env *env, const upb_handlers *h,
9545 upb_bytessink *output) {
9546 const size_t initial_bufsize = 256;
9547 const size_t initial_segbufsize = 16;
Josh Habermane8ed0212015-06-08 17:56:03 -07009548 /* TODO(haberman): make this configurable. */
Chris Fallind3262772015-05-14 18:24:26 -07009549 const size_t stack_size = 64;
9550#ifndef NDEBUG
9551 const size_t size_before = upb_env_bytesallocated(env);
9552#endif
Chris Fallin91473dc2014-12-12 15:58:26 -08009553
Chris Fallind3262772015-05-14 18:24:26 -07009554 upb_pb_encoder *e = upb_env_malloc(env, sizeof(upb_pb_encoder));
9555 if (!e) return NULL;
Chris Fallin91473dc2014-12-12 15:58:26 -08009556
Chris Fallind3262772015-05-14 18:24:26 -07009557 e->buf = upb_env_malloc(env, initial_bufsize);
9558 e->segbuf = upb_env_malloc(env, initial_segbufsize * sizeof(*e->segbuf));
9559 e->stack = upb_env_malloc(env, stack_size * sizeof(*e->stack));
9560
9561 if (!e->buf || !e->segbuf || !e->stack) {
9562 return NULL;
Chris Fallin91473dc2014-12-12 15:58:26 -08009563 }
9564
Chris Fallind3262772015-05-14 18:24:26 -07009565 e->limit = e->buf + initial_bufsize;
9566 e->seglimit = e->segbuf + initial_segbufsize;
9567 e->stacklimit = e->stack + stack_size;
Chris Fallin91473dc2014-12-12 15:58:26 -08009568
Chris Fallin91473dc2014-12-12 15:58:26 -08009569 upb_pb_encoder_reset(e);
Chris Fallind3262772015-05-14 18:24:26 -07009570 upb_sink_reset(&e->input_, h, e);
9571
9572 e->env = env;
Chris Fallin91473dc2014-12-12 15:58:26 -08009573 e->output_ = output;
9574 e->subc = output->closure;
Chris Fallind3262772015-05-14 18:24:26 -07009575 e->ptr = e->buf;
Chris Fallin91473dc2014-12-12 15:58:26 -08009576
Josh Habermane8ed0212015-06-08 17:56:03 -07009577 /* If this fails, increase the value in encoder.h. */
Chris Fallind3262772015-05-14 18:24:26 -07009578 assert(upb_env_bytesallocated(env) - size_before <= UPB_PB_ENCODER_SIZE);
9579 return e;
Chris Fallin91473dc2014-12-12 15:58:26 -08009580}
9581
9582upb_sink *upb_pb_encoder_input(upb_pb_encoder *e) { return &e->input_; }
Chris Fallin91473dc2014-12-12 15:58:26 -08009583
9584
9585#include <stdio.h>
9586#include <stdlib.h>
9587#include <string.h>
9588
Josh Haberman94e54b32016-04-14 12:06:09 -07009589upb_filedef **upb_loaddescriptor(const char *buf, size_t n, const void *owner,
9590 upb_status *status) {
Josh Habermane8ed0212015-06-08 17:56:03 -07009591 /* Create handlers. */
9592 const upb_pbdecodermethod *decoder_m;
Chris Fallin91473dc2014-12-12 15:58:26 -08009593 const upb_handlers *reader_h = upb_descreader_newhandlers(&reader_h);
Chris Fallind3262772015-05-14 18:24:26 -07009594 upb_env env;
Josh Habermane8ed0212015-06-08 17:56:03 -07009595 upb_pbdecodermethodopts opts;
9596 upb_pbdecoder *decoder;
9597 upb_descreader *reader;
9598 bool ok;
Josh Haberman94e54b32016-04-14 12:06:09 -07009599 size_t i;
9600 upb_filedef **ret = NULL;
Josh Habermane8ed0212015-06-08 17:56:03 -07009601
9602 upb_pbdecodermethodopts_init(&opts, reader_h);
9603 decoder_m = upb_pbdecodermethod_new(&opts, &decoder_m);
9604
Chris Fallind3262772015-05-14 18:24:26 -07009605 upb_env_init(&env);
9606 upb_env_reporterrorsto(&env, status);
Chris Fallin91473dc2014-12-12 15:58:26 -08009607
Josh Habermane8ed0212015-06-08 17:56:03 -07009608 reader = upb_descreader_create(&env, reader_h);
9609 decoder = upb_pbdecoder_create(&env, decoder_m, upb_descreader_input(reader));
Chris Fallin91473dc2014-12-12 15:58:26 -08009610
Josh Habermane8ed0212015-06-08 17:56:03 -07009611 /* Push input data. */
Josh Haberman94e54b32016-04-14 12:06:09 -07009612 ok = upb_bufsrc_putbuf(buf, n, upb_pbdecoder_input(decoder));
Chris Fallin91473dc2014-12-12 15:58:26 -08009613
Josh Haberman94e54b32016-04-14 12:06:09 -07009614 if (!ok) {
9615 goto cleanup;
9616 }
9617
9618 ret = malloc(sizeof (*ret) * (upb_descreader_filecount(reader) + 1));
9619
9620 if (!ret) {
9621 goto cleanup;
9622 }
9623
9624 for (i = 0; i < upb_descreader_filecount(reader); i++) {
9625 ret[i] = upb_descreader_file(reader, i);
9626 upb_filedef_ref(ret[i], owner);
9627 }
9628
9629 ret[i] = NULL;
Chris Fallin91473dc2014-12-12 15:58:26 -08009630
9631cleanup:
Chris Fallind3262772015-05-14 18:24:26 -07009632 upb_env_uninit(&env);
Chris Fallin91473dc2014-12-12 15:58:26 -08009633 upb_handlers_unref(reader_h, &reader_h);
9634 upb_pbdecodermethod_unref(decoder_m, &decoder_m);
9635 return ret;
9636}
Chris Fallin91473dc2014-12-12 15:58:26 -08009637/*
Josh Haberman181c7f22015-07-15 11:05:10 -07009638 * upb::pb::TextPrinter
Chris Fallin91473dc2014-12-12 15:58:26 -08009639 *
9640 * OPT: This is not optimized at all. It uses printf() which parses the format
9641 * string every time, and it allocates memory for every put.
9642 */
9643
9644
9645#include <ctype.h>
9646#include <float.h>
9647#include <inttypes.h>
Josh Habermane8ed0212015-06-08 17:56:03 -07009648#include <stdarg.h>
Chris Fallin91473dc2014-12-12 15:58:26 -08009649#include <stdio.h>
9650#include <stdlib.h>
9651#include <string.h>
9652
9653
Chris Fallind3262772015-05-14 18:24:26 -07009654struct upb_textprinter {
9655 upb_sink input_;
9656 upb_bytessink *output_;
9657 int indent_depth_;
9658 bool single_line_;
9659 void *subc;
9660};
9661
Chris Fallin91473dc2014-12-12 15:58:26 -08009662#define CHECK(x) if ((x) < 0) goto err;
9663
9664static const char *shortname(const char *longname) {
9665 const char *last = strrchr(longname, '.');
9666 return last ? last + 1 : longname;
9667}
9668
9669static int indent(upb_textprinter *p) {
9670 int i;
9671 if (!p->single_line_)
9672 for (i = 0; i < p->indent_depth_; i++)
9673 upb_bytessink_putbuf(p->output_, p->subc, " ", 2, NULL);
9674 return 0;
9675}
9676
9677static int endfield(upb_textprinter *p) {
9678 const char ch = (p->single_line_ ? ' ' : '\n');
9679 upb_bytessink_putbuf(p->output_, p->subc, &ch, 1, NULL);
9680 return 0;
9681}
9682
9683static int putescaped(upb_textprinter *p, const char *buf, size_t len,
9684 bool preserve_utf8) {
Josh Habermane8ed0212015-06-08 17:56:03 -07009685 /* Based on CEscapeInternal() from Google's protobuf release. */
Chris Fallin91473dc2014-12-12 15:58:26 -08009686 char dstbuf[4096], *dst = dstbuf, *dstend = dstbuf + sizeof(dstbuf);
9687 const char *end = buf + len;
9688
Josh Habermane8ed0212015-06-08 17:56:03 -07009689 /* I think hex is prettier and more useful, but proto2 uses octal; should
9690 * investigate whether it can parse hex also. */
Chris Fallin91473dc2014-12-12 15:58:26 -08009691 const bool use_hex = false;
Josh Habermane8ed0212015-06-08 17:56:03 -07009692 bool last_hex_escape = false; /* true if last output char was \xNN */
Chris Fallin91473dc2014-12-12 15:58:26 -08009693
9694 for (; buf < end; buf++) {
Josh Habermane8ed0212015-06-08 17:56:03 -07009695 bool is_hex_escape;
9696
Chris Fallin91473dc2014-12-12 15:58:26 -08009697 if (dstend - dst < 4) {
9698 upb_bytessink_putbuf(p->output_, p->subc, dstbuf, dst - dstbuf, NULL);
9699 dst = dstbuf;
9700 }
9701
Josh Habermane8ed0212015-06-08 17:56:03 -07009702 is_hex_escape = false;
Chris Fallin91473dc2014-12-12 15:58:26 -08009703 switch (*buf) {
9704 case '\n': *(dst++) = '\\'; *(dst++) = 'n'; break;
9705 case '\r': *(dst++) = '\\'; *(dst++) = 'r'; break;
9706 case '\t': *(dst++) = '\\'; *(dst++) = 't'; break;
9707 case '\"': *(dst++) = '\\'; *(dst++) = '\"'; break;
9708 case '\'': *(dst++) = '\\'; *(dst++) = '\''; break;
9709 case '\\': *(dst++) = '\\'; *(dst++) = '\\'; break;
9710 default:
Josh Habermane8ed0212015-06-08 17:56:03 -07009711 /* Note that if we emit \xNN and the buf character after that is a hex
9712 * digit then that digit must be escaped too to prevent it being
9713 * interpreted as part of the character code by C. */
Chris Fallin91473dc2014-12-12 15:58:26 -08009714 if ((!preserve_utf8 || (uint8_t)*buf < 0x80) &&
9715 (!isprint(*buf) || (last_hex_escape && isxdigit(*buf)))) {
9716 sprintf(dst, (use_hex ? "\\x%02x" : "\\%03o"), (uint8_t)*buf);
9717 is_hex_escape = use_hex;
9718 dst += 4;
9719 } else {
9720 *(dst++) = *buf; break;
9721 }
9722 }
9723 last_hex_escape = is_hex_escape;
9724 }
Josh Habermane8ed0212015-06-08 17:56:03 -07009725 /* Flush remaining data. */
Chris Fallin91473dc2014-12-12 15:58:26 -08009726 upb_bytessink_putbuf(p->output_, p->subc, dstbuf, dst - dstbuf, NULL);
9727 return 0;
9728}
9729
9730bool putf(upb_textprinter *p, const char *fmt, ...) {
9731 va_list args;
Josh Habermane8ed0212015-06-08 17:56:03 -07009732 va_list args_copy;
9733 char *str;
9734 int written;
9735 int len;
9736 bool ok;
9737
Chris Fallin91473dc2014-12-12 15:58:26 -08009738 va_start(args, fmt);
9739
Josh Habermane8ed0212015-06-08 17:56:03 -07009740 /* Run once to get the length of the string. */
9741 _upb_va_copy(args_copy, args);
9742 len = _upb_vsnprintf(NULL, 0, fmt, args_copy);
Chris Fallin91473dc2014-12-12 15:58:26 -08009743 va_end(args_copy);
9744
Josh Habermane8ed0212015-06-08 17:56:03 -07009745 /* + 1 for NULL terminator (vsprintf() requires it even if we don't). */
9746 str = malloc(len + 1);
Chris Fallin91473dc2014-12-12 15:58:26 -08009747 if (!str) return false;
Josh Habermane8ed0212015-06-08 17:56:03 -07009748 written = vsprintf(str, fmt, args);
Chris Fallin91473dc2014-12-12 15:58:26 -08009749 va_end(args);
9750 UPB_ASSERT_VAR(written, written == len);
9751
Josh Habermane8ed0212015-06-08 17:56:03 -07009752 ok = upb_bytessink_putbuf(p->output_, p->subc, str, len, NULL);
Chris Fallin91473dc2014-12-12 15:58:26 -08009753 free(str);
9754 return ok;
9755}
9756
9757
9758/* handlers *******************************************************************/
9759
9760static bool textprinter_startmsg(void *c, const void *hd) {
Chris Fallin91473dc2014-12-12 15:58:26 -08009761 upb_textprinter *p = c;
Josh Habermane8ed0212015-06-08 17:56:03 -07009762 UPB_UNUSED(hd);
Chris Fallin91473dc2014-12-12 15:58:26 -08009763 if (p->indent_depth_ == 0) {
9764 upb_bytessink_start(p->output_, 0, &p->subc);
9765 }
9766 return true;
9767}
9768
9769static bool textprinter_endmsg(void *c, const void *hd, upb_status *s) {
Josh Habermane8ed0212015-06-08 17:56:03 -07009770 upb_textprinter *p = c;
Chris Fallin91473dc2014-12-12 15:58:26 -08009771 UPB_UNUSED(hd);
9772 UPB_UNUSED(s);
Chris Fallin91473dc2014-12-12 15:58:26 -08009773 if (p->indent_depth_ == 0) {
9774 upb_bytessink_end(p->output_);
9775 }
9776 return true;
9777}
9778
9779#define TYPE(name, ctype, fmt) \
9780 static bool textprinter_put ## name(void *closure, const void *handler_data, \
9781 ctype val) { \
9782 upb_textprinter *p = closure; \
9783 const upb_fielddef *f = handler_data; \
9784 CHECK(indent(p)); \
9785 putf(p, "%s: " fmt, upb_fielddef_name(f), val); \
9786 CHECK(endfield(p)); \
9787 return true; \
9788 err: \
9789 return false; \
9790}
9791
9792static bool textprinter_putbool(void *closure, const void *handler_data,
9793 bool val) {
9794 upb_textprinter *p = closure;
9795 const upb_fielddef *f = handler_data;
9796 CHECK(indent(p));
9797 putf(p, "%s: %s", upb_fielddef_name(f), val ? "true" : "false");
9798 CHECK(endfield(p));
9799 return true;
9800err:
9801 return false;
9802}
9803
9804#define STRINGIFY_HELPER(x) #x
9805#define STRINGIFY_MACROVAL(x) STRINGIFY_HELPER(x)
9806
9807TYPE(int32, int32_t, "%" PRId32)
9808TYPE(int64, int64_t, "%" PRId64)
Josh Habermane8ed0212015-06-08 17:56:03 -07009809TYPE(uint32, uint32_t, "%" PRIu32)
Chris Fallin91473dc2014-12-12 15:58:26 -08009810TYPE(uint64, uint64_t, "%" PRIu64)
9811TYPE(float, float, "%." STRINGIFY_MACROVAL(FLT_DIG) "g")
9812TYPE(double, double, "%." STRINGIFY_MACROVAL(DBL_DIG) "g")
9813
9814#undef TYPE
9815
Josh Habermane8ed0212015-06-08 17:56:03 -07009816/* Output a symbolic value from the enum if found, else just print as int32. */
Chris Fallin91473dc2014-12-12 15:58:26 -08009817static bool textprinter_putenum(void *closure, const void *handler_data,
9818 int32_t val) {
9819 upb_textprinter *p = closure;
9820 const upb_fielddef *f = handler_data;
9821 const upb_enumdef *enum_def = upb_downcast_enumdef(upb_fielddef_subdef(f));
9822 const char *label = upb_enumdef_iton(enum_def, val);
9823 if (label) {
9824 indent(p);
9825 putf(p, "%s: %s", upb_fielddef_name(f), label);
9826 endfield(p);
9827 } else {
9828 if (!textprinter_putint32(closure, handler_data, val))
9829 return false;
9830 }
9831 return true;
9832}
9833
9834static void *textprinter_startstr(void *closure, const void *handler_data,
9835 size_t size_hint) {
Josh Habermane8ed0212015-06-08 17:56:03 -07009836 upb_textprinter *p = closure;
Chris Fallin91473dc2014-12-12 15:58:26 -08009837 const upb_fielddef *f = handler_data;
9838 UPB_UNUSED(size_hint);
Chris Fallin91473dc2014-12-12 15:58:26 -08009839 indent(p);
9840 putf(p, "%s: \"", upb_fielddef_name(f));
9841 return p;
9842}
9843
9844static bool textprinter_endstr(void *closure, const void *handler_data) {
Chris Fallin91473dc2014-12-12 15:58:26 -08009845 upb_textprinter *p = closure;
Josh Habermane8ed0212015-06-08 17:56:03 -07009846 UPB_UNUSED(handler_data);
Chris Fallin91473dc2014-12-12 15:58:26 -08009847 putf(p, "\"");
9848 endfield(p);
9849 return true;
9850}
9851
9852static size_t textprinter_putstr(void *closure, const void *hd, const char *buf,
9853 size_t len, const upb_bufhandle *handle) {
Chris Fallin91473dc2014-12-12 15:58:26 -08009854 upb_textprinter *p = closure;
9855 const upb_fielddef *f = hd;
Josh Habermane8ed0212015-06-08 17:56:03 -07009856 UPB_UNUSED(handle);
Chris Fallin91473dc2014-12-12 15:58:26 -08009857 CHECK(putescaped(p, buf, len, upb_fielddef_type(f) == UPB_TYPE_STRING));
9858 return len;
9859err:
9860 return 0;
9861}
9862
9863static void *textprinter_startsubmsg(void *closure, const void *handler_data) {
9864 upb_textprinter *p = closure;
9865 const char *name = handler_data;
9866 CHECK(indent(p));
9867 putf(p, "%s {%c", name, p->single_line_ ? ' ' : '\n');
9868 p->indent_depth_++;
9869 return p;
9870err:
9871 return UPB_BREAK;
9872}
9873
9874static bool textprinter_endsubmsg(void *closure, const void *handler_data) {
Chris Fallin91473dc2014-12-12 15:58:26 -08009875 upb_textprinter *p = closure;
Josh Habermane8ed0212015-06-08 17:56:03 -07009876 UPB_UNUSED(handler_data);
Chris Fallin91473dc2014-12-12 15:58:26 -08009877 p->indent_depth_--;
9878 CHECK(indent(p));
9879 upb_bytessink_putbuf(p->output_, p->subc, "}", 1, NULL);
9880 CHECK(endfield(p));
9881 return true;
9882err:
9883 return false;
9884}
9885
Chris Fallin91473dc2014-12-12 15:58:26 -08009886static void onmreg(const void *c, upb_handlers *h) {
Chris Fallin91473dc2014-12-12 15:58:26 -08009887 const upb_msgdef *m = upb_handlers_msgdef(h);
Josh Habermane8ed0212015-06-08 17:56:03 -07009888 upb_msg_field_iter i;
9889 UPB_UNUSED(c);
Chris Fallin91473dc2014-12-12 15:58:26 -08009890
9891 upb_handlers_setstartmsg(h, textprinter_startmsg, NULL);
9892 upb_handlers_setendmsg(h, textprinter_endmsg, NULL);
9893
Chris Fallinfcd88892015-01-13 18:14:39 -08009894 for(upb_msg_field_begin(&i, m);
9895 !upb_msg_field_done(&i);
9896 upb_msg_field_next(&i)) {
Chris Fallin91473dc2014-12-12 15:58:26 -08009897 upb_fielddef *f = upb_msg_iter_field(&i);
9898 upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
9899 upb_handlerattr_sethandlerdata(&attr, f);
9900 switch (upb_fielddef_type(f)) {
9901 case UPB_TYPE_INT32:
9902 upb_handlers_setint32(h, f, textprinter_putint32, &attr);
9903 break;
9904 case UPB_TYPE_INT64:
9905 upb_handlers_setint64(h, f, textprinter_putint64, &attr);
9906 break;
9907 case UPB_TYPE_UINT32:
9908 upb_handlers_setuint32(h, f, textprinter_putuint32, &attr);
9909 break;
9910 case UPB_TYPE_UINT64:
9911 upb_handlers_setuint64(h, f, textprinter_putuint64, &attr);
9912 break;
9913 case UPB_TYPE_FLOAT:
9914 upb_handlers_setfloat(h, f, textprinter_putfloat, &attr);
9915 break;
9916 case UPB_TYPE_DOUBLE:
9917 upb_handlers_setdouble(h, f, textprinter_putdouble, &attr);
9918 break;
9919 case UPB_TYPE_BOOL:
9920 upb_handlers_setbool(h, f, textprinter_putbool, &attr);
9921 break;
9922 case UPB_TYPE_STRING:
9923 case UPB_TYPE_BYTES:
9924 upb_handlers_setstartstr(h, f, textprinter_startstr, &attr);
9925 upb_handlers_setstring(h, f, textprinter_putstr, &attr);
9926 upb_handlers_setendstr(h, f, textprinter_endstr, &attr);
9927 break;
9928 case UPB_TYPE_MESSAGE: {
9929 const char *name =
9930 upb_fielddef_istagdelim(f)
9931 ? shortname(upb_msgdef_fullname(upb_fielddef_msgsubdef(f)))
9932 : upb_fielddef_name(f);
9933 upb_handlerattr_sethandlerdata(&attr, name);
9934 upb_handlers_setstartsubmsg(h, f, textprinter_startsubmsg, &attr);
9935 upb_handlers_setendsubmsg(h, f, textprinter_endsubmsg, &attr);
9936 break;
9937 }
9938 case UPB_TYPE_ENUM:
9939 upb_handlers_setint32(h, f, textprinter_putenum, &attr);
9940 break;
9941 }
9942 }
9943}
9944
Chris Fallind3262772015-05-14 18:24:26 -07009945static void textprinter_reset(upb_textprinter *p, bool single_line) {
9946 p->single_line_ = single_line;
9947 p->indent_depth_ = 0;
9948}
9949
9950
9951/* Public API *****************************************************************/
9952
9953upb_textprinter *upb_textprinter_create(upb_env *env, const upb_handlers *h,
9954 upb_bytessink *output) {
9955 upb_textprinter *p = upb_env_malloc(env, sizeof(upb_textprinter));
9956 if (!p) return NULL;
9957
9958 p->output_ = output;
9959 upb_sink_reset(&p->input_, h, p);
9960 textprinter_reset(p, false);
9961
9962 return p;
9963}
9964
Chris Fallin91473dc2014-12-12 15:58:26 -08009965const upb_handlers *upb_textprinter_newhandlers(const upb_msgdef *m,
9966 const void *owner) {
9967 return upb_handlers_newfrozen(m, owner, &onmreg, NULL);
9968}
9969
9970upb_sink *upb_textprinter_input(upb_textprinter *p) { return &p->input_; }
9971
Chris Fallin91473dc2014-12-12 15:58:26 -08009972void upb_textprinter_setsingleline(upb_textprinter *p, bool single_line) {
9973 p->single_line_ = single_line;
9974}
Chris Fallin91473dc2014-12-12 15:58:26 -08009975
9976
Josh Habermane8ed0212015-06-08 17:56:03 -07009977/* Index is descriptor type. */
Chris Fallin91473dc2014-12-12 15:58:26 -08009978const uint8_t upb_pb_native_wire_types[] = {
Josh Habermane8ed0212015-06-08 17:56:03 -07009979 UPB_WIRE_TYPE_END_GROUP, /* ENDGROUP */
9980 UPB_WIRE_TYPE_64BIT, /* DOUBLE */
9981 UPB_WIRE_TYPE_32BIT, /* FLOAT */
9982 UPB_WIRE_TYPE_VARINT, /* INT64 */
9983 UPB_WIRE_TYPE_VARINT, /* UINT64 */
9984 UPB_WIRE_TYPE_VARINT, /* INT32 */
9985 UPB_WIRE_TYPE_64BIT, /* FIXED64 */
9986 UPB_WIRE_TYPE_32BIT, /* FIXED32 */
9987 UPB_WIRE_TYPE_VARINT, /* BOOL */
9988 UPB_WIRE_TYPE_DELIMITED, /* STRING */
9989 UPB_WIRE_TYPE_START_GROUP, /* GROUP */
9990 UPB_WIRE_TYPE_DELIMITED, /* MESSAGE */
9991 UPB_WIRE_TYPE_DELIMITED, /* BYTES */
9992 UPB_WIRE_TYPE_VARINT, /* UINT32 */
9993 UPB_WIRE_TYPE_VARINT, /* ENUM */
9994 UPB_WIRE_TYPE_32BIT, /* SFIXED32 */
9995 UPB_WIRE_TYPE_64BIT, /* SFIXED64 */
9996 UPB_WIRE_TYPE_VARINT, /* SINT32 */
9997 UPB_WIRE_TYPE_VARINT, /* SINT64 */
Chris Fallin91473dc2014-12-12 15:58:26 -08009998};
9999
Josh Habermane8ed0212015-06-08 17:56:03 -070010000/* A basic branch-based decoder, uses 32-bit values to get good performance
10001 * on 32-bit architectures (but performs well on 64-bits also).
10002 * This scheme comes from the original Google Protobuf implementation
10003 * (proto2). */
Chris Fallin91473dc2014-12-12 15:58:26 -080010004upb_decoderet upb_vdecode_max8_branch32(upb_decoderet r) {
10005 upb_decoderet err = {NULL, 0};
10006 const char *p = r.p;
10007 uint32_t low = (uint32_t)r.val;
10008 uint32_t high = 0;
10009 uint32_t b;
10010 b = *(p++); low |= (b & 0x7fU) << 14; if (!(b & 0x80)) goto done;
10011 b = *(p++); low |= (b & 0x7fU) << 21; if (!(b & 0x80)) goto done;
10012 b = *(p++); low |= (b & 0x7fU) << 28;
10013 high = (b & 0x7fU) >> 4; if (!(b & 0x80)) goto done;
10014 b = *(p++); high |= (b & 0x7fU) << 3; if (!(b & 0x80)) goto done;
10015 b = *(p++); high |= (b & 0x7fU) << 10; if (!(b & 0x80)) goto done;
10016 b = *(p++); high |= (b & 0x7fU) << 17; if (!(b & 0x80)) goto done;
10017 b = *(p++); high |= (b & 0x7fU) << 24; if (!(b & 0x80)) goto done;
10018 b = *(p++); high |= (b & 0x7fU) << 31; if (!(b & 0x80)) goto done;
10019 return err;
10020
10021done:
10022 r.val = ((uint64_t)high << 32) | low;
10023 r.p = p;
10024 return r;
10025}
10026
Josh Habermane8ed0212015-06-08 17:56:03 -070010027/* Like the previous, but uses 64-bit values. */
Chris Fallin91473dc2014-12-12 15:58:26 -080010028upb_decoderet upb_vdecode_max8_branch64(upb_decoderet r) {
10029 const char *p = r.p;
10030 uint64_t val = r.val;
10031 uint64_t b;
10032 upb_decoderet err = {NULL, 0};
10033 b = *(p++); val |= (b & 0x7fU) << 14; if (!(b & 0x80)) goto done;
10034 b = *(p++); val |= (b & 0x7fU) << 21; if (!(b & 0x80)) goto done;
10035 b = *(p++); val |= (b & 0x7fU) << 28; if (!(b & 0x80)) goto done;
10036 b = *(p++); val |= (b & 0x7fU) << 35; if (!(b & 0x80)) goto done;
10037 b = *(p++); val |= (b & 0x7fU) << 42; if (!(b & 0x80)) goto done;
10038 b = *(p++); val |= (b & 0x7fU) << 49; if (!(b & 0x80)) goto done;
10039 b = *(p++); val |= (b & 0x7fU) << 56; if (!(b & 0x80)) goto done;
10040 b = *(p++); val |= (b & 0x7fU) << 63; if (!(b & 0x80)) goto done;
10041 return err;
10042
10043done:
10044 r.val = val;
10045 r.p = p;
10046 return r;
10047}
10048
Josh Habermane8ed0212015-06-08 17:56:03 -070010049/* Given an encoded varint v, returns an integer with a single bit set that
10050 * indicates the end of the varint. Subtracting one from this value will
10051 * yield a mask that leaves only bits that are part of the varint. Returns
10052 * 0 if the varint is unterminated. */
Chris Fallin91473dc2014-12-12 15:58:26 -080010053static uint64_t upb_get_vstopbit(uint64_t v) {
10054 uint64_t cbits = v | 0x7f7f7f7f7f7f7f7fULL;
10055 return ~cbits & (cbits+1);
10056}
10057
Josh Habermane8ed0212015-06-08 17:56:03 -070010058/* A branchless decoder. Credit to Pascal Massimino for the bit-twiddling. */
Chris Fallin91473dc2014-12-12 15:58:26 -080010059upb_decoderet upb_vdecode_max8_massimino(upb_decoderet r) {
10060 uint64_t b;
Josh Habermane8ed0212015-06-08 17:56:03 -070010061 uint64_t stop_bit;
10062 upb_decoderet my_r;
Chris Fallin91473dc2014-12-12 15:58:26 -080010063 memcpy(&b, r.p, sizeof(b));
Josh Habermane8ed0212015-06-08 17:56:03 -070010064 stop_bit = upb_get_vstopbit(b);
Chris Fallin91473dc2014-12-12 15:58:26 -080010065 b = (b & 0x7f7f7f7f7f7f7f7fULL) & (stop_bit - 1);
10066 b += b & 0x007f007f007f007fULL;
10067 b += 3 * (b & 0x0000ffff0000ffffULL);
10068 b += 15 * (b & 0x00000000ffffffffULL);
10069 if (stop_bit == 0) {
Josh Habermane8ed0212015-06-08 17:56:03 -070010070 /* Error: unterminated varint. */
Chris Fallin91473dc2014-12-12 15:58:26 -080010071 upb_decoderet err_r = {(void*)0, 0};
10072 return err_r;
10073 }
Josh Habermane8ed0212015-06-08 17:56:03 -070010074 my_r = upb_decoderet_make(r.p + ((__builtin_ctzll(stop_bit) + 1) / 8),
10075 r.val | (b << 7));
Chris Fallin91473dc2014-12-12 15:58:26 -080010076 return my_r;
10077}
10078
Josh Habermane8ed0212015-06-08 17:56:03 -070010079/* A branchless decoder. Credit to Daniel Wright for the bit-twiddling. */
Chris Fallin91473dc2014-12-12 15:58:26 -080010080upb_decoderet upb_vdecode_max8_wright(upb_decoderet r) {
10081 uint64_t b;
Josh Habermane8ed0212015-06-08 17:56:03 -070010082 uint64_t stop_bit;
10083 upb_decoderet my_r;
Chris Fallin91473dc2014-12-12 15:58:26 -080010084 memcpy(&b, r.p, sizeof(b));
Josh Habermane8ed0212015-06-08 17:56:03 -070010085 stop_bit = upb_get_vstopbit(b);
Chris Fallin91473dc2014-12-12 15:58:26 -080010086 b &= (stop_bit - 1);
10087 b = ((b & 0x7f007f007f007f00ULL) >> 1) | (b & 0x007f007f007f007fULL);
10088 b = ((b & 0xffff0000ffff0000ULL) >> 2) | (b & 0x0000ffff0000ffffULL);
10089 b = ((b & 0xffffffff00000000ULL) >> 4) | (b & 0x00000000ffffffffULL);
10090 if (stop_bit == 0) {
Josh Habermane8ed0212015-06-08 17:56:03 -070010091 /* Error: unterminated varint. */
Chris Fallin91473dc2014-12-12 15:58:26 -080010092 upb_decoderet err_r = {(void*)0, 0};
10093 return err_r;
10094 }
Josh Habermane8ed0212015-06-08 17:56:03 -070010095 my_r = upb_decoderet_make(r.p + ((__builtin_ctzll(stop_bit) + 1) / 8),
10096 r.val | (b << 14));
Chris Fallin91473dc2014-12-12 15:58:26 -080010097 return my_r;
10098}
10099
10100#line 1 "upb/json/parser.rl"
10101/*
Josh Haberman181c7f22015-07-15 11:05:10 -070010102** upb::json::Parser (upb_json_parser)
10103**
10104** A parser that uses the Ragel State Machine Compiler to generate
10105** the finite automata.
10106**
10107** Ragel only natively handles regular languages, but we can manually
10108** program it a bit to handle context-free languages like JSON, by using
10109** the "fcall" and "fret" constructs.
10110**
10111** This parser can handle the basics, but needs several things to be fleshed
10112** out:
10113**
10114** - handling of unicode escape sequences (including high surrogate pairs).
10115** - properly check and report errors for unknown fields, stack overflow,
10116** improper array nesting (or lack of nesting).
10117** - handling of base64 sequences with padding characters.
10118** - handling of push-back (non-success returns from sink functions).
10119** - handling of keys/escape-sequences/etc that span input buffers.
10120*/
Chris Fallin91473dc2014-12-12 15:58:26 -080010121
10122#include <stdio.h>
10123#include <stdint.h>
10124#include <assert.h>
10125#include <string.h>
10126#include <stdlib.h>
10127#include <errno.h>
10128
10129
Chris Fallind3262772015-05-14 18:24:26 -070010130#define UPB_JSON_MAX_DEPTH 64
10131
10132typedef struct {
10133 upb_sink sink;
10134
Josh Habermane8ed0212015-06-08 17:56:03 -070010135 /* The current message in which we're parsing, and the field whose value we're
10136 * expecting next. */
Chris Fallind3262772015-05-14 18:24:26 -070010137 const upb_msgdef *m;
10138 const upb_fielddef *f;
10139
Josh Haberman78da6662016-01-13 19:05:43 -080010140 /* The table mapping json name to fielddef for this message. */
10141 upb_strtable *name_table;
10142
Josh Habermane8ed0212015-06-08 17:56:03 -070010143 /* We are in a repeated-field context, ready to emit mapentries as
10144 * submessages. This flag alters the start-of-object (open-brace) behavior to
10145 * begin a sequence of mapentry messages rather than a single submessage. */
Chris Fallind3262772015-05-14 18:24:26 -070010146 bool is_map;
10147
Josh Habermane8ed0212015-06-08 17:56:03 -070010148 /* We are in a map-entry message context. This flag is set when parsing the
10149 * value field of a single map entry and indicates to all value-field parsers
10150 * (subobjects, strings, numbers, and bools) that the map-entry submessage
10151 * should end as soon as the value is parsed. */
Chris Fallind3262772015-05-14 18:24:26 -070010152 bool is_mapentry;
10153
Josh Habermane8ed0212015-06-08 17:56:03 -070010154 /* If |is_map| or |is_mapentry| is true, |mapfield| refers to the parent
10155 * message's map field that we're currently parsing. This differs from |f|
10156 * because |f| is the field in the *current* message (i.e., the map-entry
10157 * message itself), not the parent's field that leads to this map. */
Chris Fallind3262772015-05-14 18:24:26 -070010158 const upb_fielddef *mapfield;
10159} upb_jsonparser_frame;
10160
10161struct upb_json_parser {
10162 upb_env *env;
Josh Haberman78da6662016-01-13 19:05:43 -080010163 const upb_json_parsermethod *method;
Chris Fallind3262772015-05-14 18:24:26 -070010164 upb_bytessink input_;
10165
Josh Habermane8ed0212015-06-08 17:56:03 -070010166 /* Stack to track the JSON scopes we are in. */
Chris Fallind3262772015-05-14 18:24:26 -070010167 upb_jsonparser_frame stack[UPB_JSON_MAX_DEPTH];
10168 upb_jsonparser_frame *top;
10169 upb_jsonparser_frame *limit;
10170
Josh Haberman181c7f22015-07-15 11:05:10 -070010171 upb_status status;
Chris Fallind3262772015-05-14 18:24:26 -070010172
Josh Habermane8ed0212015-06-08 17:56:03 -070010173 /* Ragel's internal parsing stack for the parsing state machine. */
Chris Fallind3262772015-05-14 18:24:26 -070010174 int current_state;
10175 int parser_stack[UPB_JSON_MAX_DEPTH];
10176 int parser_top;
10177
Josh Habermane8ed0212015-06-08 17:56:03 -070010178 /* The handle for the current buffer. */
Chris Fallind3262772015-05-14 18:24:26 -070010179 const upb_bufhandle *handle;
10180
Josh Habermane8ed0212015-06-08 17:56:03 -070010181 /* Accumulate buffer. See details in parser.rl. */
Chris Fallind3262772015-05-14 18:24:26 -070010182 const char *accumulated;
10183 size_t accumulated_len;
10184 char *accumulate_buf;
10185 size_t accumulate_buf_size;
10186
Josh Habermane8ed0212015-06-08 17:56:03 -070010187 /* Multi-part text data. See details in parser.rl. */
Chris Fallind3262772015-05-14 18:24:26 -070010188 int multipart_state;
10189 upb_selector_t string_selector;
10190
Josh Habermane8ed0212015-06-08 17:56:03 -070010191 /* Input capture. See details in parser.rl. */
Chris Fallind3262772015-05-14 18:24:26 -070010192 const char *capture;
10193
Josh Habermane8ed0212015-06-08 17:56:03 -070010194 /* Intermediate result of parsing a unicode escape sequence. */
Chris Fallind3262772015-05-14 18:24:26 -070010195 uint32_t digit;
10196};
10197
Josh Haberman78da6662016-01-13 19:05:43 -080010198struct upb_json_parsermethod {
10199 upb_refcounted base;
10200
10201 upb_byteshandler input_handler_;
10202
10203 /* Mainly for the purposes of refcounting, so all the fielddefs we point
10204 * to stay alive. */
10205 const upb_msgdef *msg;
10206
10207 /* Keys are upb_msgdef*, values are upb_strtable (json_name -> fielddef) */
10208 upb_inttable name_tables;
10209};
10210
Chris Fallin91473dc2014-12-12 15:58:26 -080010211#define PARSER_CHECK_RETURN(x) if (!(x)) return false
10212
Josh Habermane8ed0212015-06-08 17:56:03 -070010213/* Used to signal that a capture has been suspended. */
Chris Fallin97b663a2015-01-09 16:15:22 -080010214static char suspend_capture;
10215
Chris Fallin91473dc2014-12-12 15:58:26 -080010216static upb_selector_t getsel_for_handlertype(upb_json_parser *p,
10217 upb_handlertype_t type) {
10218 upb_selector_t sel;
10219 bool ok = upb_handlers_getselector(p->top->f, type, &sel);
10220 UPB_ASSERT_VAR(ok, ok);
10221 return sel;
10222}
10223
10224static upb_selector_t parser_getsel(upb_json_parser *p) {
10225 return getsel_for_handlertype(
10226 p, upb_handlers_getprimitivehandlertype(p->top->f));
10227}
10228
Chris Fallin91473dc2014-12-12 15:58:26 -080010229static bool check_stack(upb_json_parser *p) {
10230 if ((p->top + 1) == p->limit) {
Josh Haberman181c7f22015-07-15 11:05:10 -070010231 upb_status_seterrmsg(&p->status, "Nesting too deep");
10232 upb_env_reporterror(p->env, &p->status);
Chris Fallin91473dc2014-12-12 15:58:26 -080010233 return false;
10234 }
10235
10236 return true;
10237}
10238
Josh Haberman78da6662016-01-13 19:05:43 -080010239static void set_name_table(upb_json_parser *p, upb_jsonparser_frame *frame) {
10240 upb_value v;
10241 bool ok = upb_inttable_lookupptr(&p->method->name_tables, frame->m, &v);
10242 UPB_ASSERT_VAR(ok, ok);
10243 frame->name_table = upb_value_getptr(v);
10244}
10245
Josh Habermane8ed0212015-06-08 17:56:03 -070010246/* There are GCC/Clang built-ins for overflow checking which we could start
10247 * using if there was any performance benefit to it. */
Chris Fallin91473dc2014-12-12 15:58:26 -080010248
Chris Fallin97b663a2015-01-09 16:15:22 -080010249static bool checked_add(size_t a, size_t b, size_t *c) {
10250 if (SIZE_MAX - a < b) return false;
10251 *c = a + b;
Chris Fallin91473dc2014-12-12 15:58:26 -080010252 return true;
10253}
10254
Chris Fallin97b663a2015-01-09 16:15:22 -080010255static size_t saturating_multiply(size_t a, size_t b) {
Josh Habermane8ed0212015-06-08 17:56:03 -070010256 /* size_t is unsigned, so this is defined behavior even on overflow. */
Chris Fallin97b663a2015-01-09 16:15:22 -080010257 size_t ret = a * b;
10258 if (b != 0 && ret / b != a) {
10259 ret = SIZE_MAX;
Chris Fallin91473dc2014-12-12 15:58:26 -080010260 }
Chris Fallin97b663a2015-01-09 16:15:22 -080010261 return ret;
Chris Fallin91473dc2014-12-12 15:58:26 -080010262}
10263
Chris Fallin91473dc2014-12-12 15:58:26 -080010264
Chris Fallin97b663a2015-01-09 16:15:22 -080010265/* Base64 decoding ************************************************************/
Chris Fallin91473dc2014-12-12 15:58:26 -080010266
Josh Habermane8ed0212015-06-08 17:56:03 -070010267/* TODO(haberman): make this streaming. */
Chris Fallin91473dc2014-12-12 15:58:26 -080010268
10269static const signed char b64table[] = {
10270 -1, -1, -1, -1, -1, -1, -1, -1,
10271 -1, -1, -1, -1, -1, -1, -1, -1,
10272 -1, -1, -1, -1, -1, -1, -1, -1,
10273 -1, -1, -1, -1, -1, -1, -1, -1,
10274 -1, -1, -1, -1, -1, -1, -1, -1,
10275 -1, -1, -1, 62/*+*/, -1, -1, -1, 63/*/ */,
10276 52/*0*/, 53/*1*/, 54/*2*/, 55/*3*/, 56/*4*/, 57/*5*/, 58/*6*/, 59/*7*/,
10277 60/*8*/, 61/*9*/, -1, -1, -1, -1, -1, -1,
10278 -1, 0/*A*/, 1/*B*/, 2/*C*/, 3/*D*/, 4/*E*/, 5/*F*/, 6/*G*/,
10279 07/*H*/, 8/*I*/, 9/*J*/, 10/*K*/, 11/*L*/, 12/*M*/, 13/*N*/, 14/*O*/,
10280 15/*P*/, 16/*Q*/, 17/*R*/, 18/*S*/, 19/*T*/, 20/*U*/, 21/*V*/, 22/*W*/,
10281 23/*X*/, 24/*Y*/, 25/*Z*/, -1, -1, -1, -1, -1,
10282 -1, 26/*a*/, 27/*b*/, 28/*c*/, 29/*d*/, 30/*e*/, 31/*f*/, 32/*g*/,
10283 33/*h*/, 34/*i*/, 35/*j*/, 36/*k*/, 37/*l*/, 38/*m*/, 39/*n*/, 40/*o*/,
10284 41/*p*/, 42/*q*/, 43/*r*/, 44/*s*/, 45/*t*/, 46/*u*/, 47/*v*/, 48/*w*/,
10285 49/*x*/, 50/*y*/, 51/*z*/, -1, -1, -1, -1, -1,
10286 -1, -1, -1, -1, -1, -1, -1, -1,
10287 -1, -1, -1, -1, -1, -1, -1, -1,
10288 -1, -1, -1, -1, -1, -1, -1, -1,
10289 -1, -1, -1, -1, -1, -1, -1, -1,
10290 -1, -1, -1, -1, -1, -1, -1, -1,
10291 -1, -1, -1, -1, -1, -1, -1, -1,
10292 -1, -1, -1, -1, -1, -1, -1, -1,
10293 -1, -1, -1, -1, -1, -1, -1, -1,
10294 -1, -1, -1, -1, -1, -1, -1, -1,
10295 -1, -1, -1, -1, -1, -1, -1, -1,
10296 -1, -1, -1, -1, -1, -1, -1, -1,
10297 -1, -1, -1, -1, -1, -1, -1, -1,
10298 -1, -1, -1, -1, -1, -1, -1, -1,
10299 -1, -1, -1, -1, -1, -1, -1, -1,
10300 -1, -1, -1, -1, -1, -1, -1, -1,
10301 -1, -1, -1, -1, -1, -1, -1, -1
10302};
10303
Josh Habermane8ed0212015-06-08 17:56:03 -070010304/* Returns the table value sign-extended to 32 bits. Knowing that the upper
10305 * bits will be 1 for unrecognized characters makes it easier to check for
10306 * this error condition later (see below). */
Chris Fallin91473dc2014-12-12 15:58:26 -080010307int32_t b64lookup(unsigned char ch) { return b64table[ch]; }
10308
Josh Habermane8ed0212015-06-08 17:56:03 -070010309/* Returns true if the given character is not a valid base64 character or
10310 * padding. */
Chris Fallin91473dc2014-12-12 15:58:26 -080010311bool nonbase64(unsigned char ch) { return b64lookup(ch) == -1 && ch != '='; }
10312
10313static bool base64_push(upb_json_parser *p, upb_selector_t sel, const char *ptr,
10314 size_t len) {
10315 const char *limit = ptr + len;
10316 for (; ptr < limit; ptr += 4) {
Josh Habermane8ed0212015-06-08 17:56:03 -070010317 uint32_t val;
10318 char output[3];
10319
Chris Fallin91473dc2014-12-12 15:58:26 -080010320 if (limit - ptr < 4) {
Josh Haberman181c7f22015-07-15 11:05:10 -070010321 upb_status_seterrf(&p->status,
Chris Fallin91473dc2014-12-12 15:58:26 -080010322 "Base64 input for bytes field not a multiple of 4: %s",
10323 upb_fielddef_name(p->top->f));
Josh Haberman181c7f22015-07-15 11:05:10 -070010324 upb_env_reporterror(p->env, &p->status);
Chris Fallin91473dc2014-12-12 15:58:26 -080010325 return false;
10326 }
10327
Josh Habermane8ed0212015-06-08 17:56:03 -070010328 val = b64lookup(ptr[0]) << 18 |
10329 b64lookup(ptr[1]) << 12 |
10330 b64lookup(ptr[2]) << 6 |
10331 b64lookup(ptr[3]);
Chris Fallin91473dc2014-12-12 15:58:26 -080010332
Josh Habermane8ed0212015-06-08 17:56:03 -070010333 /* Test the upper bit; returns true if any of the characters returned -1. */
Chris Fallin91473dc2014-12-12 15:58:26 -080010334 if (val & 0x80000000) {
10335 goto otherchar;
10336 }
10337
Chris Fallin91473dc2014-12-12 15:58:26 -080010338 output[0] = val >> 16;
10339 output[1] = (val >> 8) & 0xff;
10340 output[2] = val & 0xff;
10341 upb_sink_putstring(&p->top->sink, sel, output, 3, NULL);
10342 }
10343 return true;
10344
10345otherchar:
10346 if (nonbase64(ptr[0]) || nonbase64(ptr[1]) || nonbase64(ptr[2]) ||
10347 nonbase64(ptr[3]) ) {
Josh Haberman181c7f22015-07-15 11:05:10 -070010348 upb_status_seterrf(&p->status,
Chris Fallin91473dc2014-12-12 15:58:26 -080010349 "Non-base64 characters in bytes field: %s",
10350 upb_fielddef_name(p->top->f));
Josh Haberman181c7f22015-07-15 11:05:10 -070010351 upb_env_reporterror(p->env, &p->status);
Chris Fallin91473dc2014-12-12 15:58:26 -080010352 return false;
10353 } if (ptr[2] == '=') {
Josh Habermane8ed0212015-06-08 17:56:03 -070010354 uint32_t val;
10355 char output;
10356
10357 /* Last group contains only two input bytes, one output byte. */
Chris Fallin91473dc2014-12-12 15:58:26 -080010358 if (ptr[0] == '=' || ptr[1] == '=' || ptr[3] != '=') {
10359 goto badpadding;
10360 }
10361
Josh Habermane8ed0212015-06-08 17:56:03 -070010362 val = b64lookup(ptr[0]) << 18 |
10363 b64lookup(ptr[1]) << 12;
Chris Fallin91473dc2014-12-12 15:58:26 -080010364
10365 assert(!(val & 0x80000000));
Josh Habermane8ed0212015-06-08 17:56:03 -070010366 output = val >> 16;
Chris Fallin91473dc2014-12-12 15:58:26 -080010367 upb_sink_putstring(&p->top->sink, sel, &output, 1, NULL);
10368 return true;
10369 } else {
Josh Habermane8ed0212015-06-08 17:56:03 -070010370 uint32_t val;
10371 char output[2];
10372
10373 /* Last group contains only three input bytes, two output bytes. */
Chris Fallin91473dc2014-12-12 15:58:26 -080010374 if (ptr[0] == '=' || ptr[1] == '=' || ptr[2] == '=') {
10375 goto badpadding;
10376 }
10377
Josh Habermane8ed0212015-06-08 17:56:03 -070010378 val = b64lookup(ptr[0]) << 18 |
10379 b64lookup(ptr[1]) << 12 |
10380 b64lookup(ptr[2]) << 6;
Chris Fallin91473dc2014-12-12 15:58:26 -080010381
Chris Fallin91473dc2014-12-12 15:58:26 -080010382 output[0] = val >> 16;
10383 output[1] = (val >> 8) & 0xff;
10384 upb_sink_putstring(&p->top->sink, sel, output, 2, NULL);
10385 return true;
10386 }
10387
10388badpadding:
Josh Haberman181c7f22015-07-15 11:05:10 -070010389 upb_status_seterrf(&p->status,
Chris Fallin91473dc2014-12-12 15:58:26 -080010390 "Incorrect base64 padding for field: %s (%.*s)",
10391 upb_fielddef_name(p->top->f),
10392 4, ptr);
Josh Haberman181c7f22015-07-15 11:05:10 -070010393 upb_env_reporterror(p->env, &p->status);
Chris Fallin91473dc2014-12-12 15:58:26 -080010394 return false;
10395}
10396
Chris Fallin91473dc2014-12-12 15:58:26 -080010397
Chris Fallin97b663a2015-01-09 16:15:22 -080010398/* Accumulate buffer **********************************************************/
Chris Fallin91473dc2014-12-12 15:58:26 -080010399
Josh Habermane8ed0212015-06-08 17:56:03 -070010400/* Functionality for accumulating a buffer.
10401 *
10402 * Some parts of the parser need an entire value as a contiguous string. For
10403 * example, to look up a member name in a hash table, or to turn a string into
10404 * a number, the relevant library routines need the input string to be in
10405 * contiguous memory, even if the value spanned two or more buffers in the
10406 * input. These routines handle that.
10407 *
10408 * In the common case we can just point to the input buffer to get this
10409 * contiguous string and avoid any actual copy. So we optimistically begin
10410 * this way. But there are a few cases where we must instead copy into a
10411 * separate buffer:
10412 *
10413 * 1. The string was not contiguous in the input (it spanned buffers).
10414 *
10415 * 2. The string included escape sequences that need to be interpreted to get
10416 * the true value in a contiguous buffer. */
Chris Fallin91473dc2014-12-12 15:58:26 -080010417
Chris Fallin97b663a2015-01-09 16:15:22 -080010418static void assert_accumulate_empty(upb_json_parser *p) {
Chris Fallinfcd88892015-01-13 18:14:39 -080010419 UPB_UNUSED(p);
Chris Fallin97b663a2015-01-09 16:15:22 -080010420 assert(p->accumulated == NULL);
10421 assert(p->accumulated_len == 0);
10422}
10423
10424static void accumulate_clear(upb_json_parser *p) {
10425 p->accumulated = NULL;
10426 p->accumulated_len = 0;
10427}
10428
Josh Habermane8ed0212015-06-08 17:56:03 -070010429/* Used internally by accumulate_append(). */
Chris Fallin97b663a2015-01-09 16:15:22 -080010430static bool accumulate_realloc(upb_json_parser *p, size_t need) {
Josh Habermane8ed0212015-06-08 17:56:03 -070010431 void *mem;
Chris Fallind3262772015-05-14 18:24:26 -070010432 size_t old_size = p->accumulate_buf_size;
10433 size_t new_size = UPB_MAX(old_size, 128);
Chris Fallin97b663a2015-01-09 16:15:22 -080010434 while (new_size < need) {
10435 new_size = saturating_multiply(new_size, 2);
10436 }
10437
Josh Habermane8ed0212015-06-08 17:56:03 -070010438 mem = upb_env_realloc(p->env, p->accumulate_buf, old_size, new_size);
Chris Fallin97b663a2015-01-09 16:15:22 -080010439 if (!mem) {
Josh Haberman181c7f22015-07-15 11:05:10 -070010440 upb_status_seterrmsg(&p->status, "Out of memory allocating buffer.");
10441 upb_env_reporterror(p->env, &p->status);
Chris Fallin97b663a2015-01-09 16:15:22 -080010442 return false;
10443 }
10444
10445 p->accumulate_buf = mem;
10446 p->accumulate_buf_size = new_size;
10447 return true;
10448}
10449
Josh Habermane8ed0212015-06-08 17:56:03 -070010450/* Logically appends the given data to the append buffer.
10451 * If "can_alias" is true, we will try to avoid actually copying, but the buffer
10452 * must be valid until the next accumulate_append() call (if any). */
Chris Fallin97b663a2015-01-09 16:15:22 -080010453static bool accumulate_append(upb_json_parser *p, const char *buf, size_t len,
10454 bool can_alias) {
Josh Habermane8ed0212015-06-08 17:56:03 -070010455 size_t need;
10456
Chris Fallin97b663a2015-01-09 16:15:22 -080010457 if (!p->accumulated && can_alias) {
10458 p->accumulated = buf;
10459 p->accumulated_len = len;
10460 return true;
10461 }
10462
Chris Fallin97b663a2015-01-09 16:15:22 -080010463 if (!checked_add(p->accumulated_len, len, &need)) {
Josh Haberman181c7f22015-07-15 11:05:10 -070010464 upb_status_seterrmsg(&p->status, "Integer overflow.");
10465 upb_env_reporterror(p->env, &p->status);
Chris Fallin97b663a2015-01-09 16:15:22 -080010466 return false;
10467 }
10468
10469 if (need > p->accumulate_buf_size && !accumulate_realloc(p, need)) {
10470 return false;
10471 }
10472
10473 if (p->accumulated != p->accumulate_buf) {
10474 memcpy(p->accumulate_buf, p->accumulated, p->accumulated_len);
10475 p->accumulated = p->accumulate_buf;
10476 }
10477
10478 memcpy(p->accumulate_buf + p->accumulated_len, buf, len);
10479 p->accumulated_len += len;
10480 return true;
10481}
10482
Josh Habermane8ed0212015-06-08 17:56:03 -070010483/* Returns a pointer to the data accumulated since the last accumulate_clear()
10484 * call, and writes the length to *len. This with point either to the input
10485 * buffer or a temporary accumulate buffer. */
Chris Fallin97b663a2015-01-09 16:15:22 -080010486static const char *accumulate_getptr(upb_json_parser *p, size_t *len) {
10487 assert(p->accumulated);
10488 *len = p->accumulated_len;
10489 return p->accumulated;
10490}
10491
10492
10493/* Mult-part text data ********************************************************/
10494
Josh Habermane8ed0212015-06-08 17:56:03 -070010495/* When we have text data in the input, it can often come in multiple segments.
10496 * For example, there may be some raw string data followed by an escape
10497 * sequence. The two segments are processed with different logic. Also buffer
10498 * seams in the input can cause multiple segments.
10499 *
10500 * As we see segments, there are two main cases for how we want to process them:
10501 *
10502 * 1. we want to push the captured input directly to string handlers.
10503 *
10504 * 2. we need to accumulate all the parts into a contiguous buffer for further
10505 * processing (field name lookup, string->number conversion, etc). */
Chris Fallin97b663a2015-01-09 16:15:22 -080010506
Josh Habermane8ed0212015-06-08 17:56:03 -070010507/* This is the set of states for p->multipart_state. */
Chris Fallin97b663a2015-01-09 16:15:22 -080010508enum {
Josh Habermane8ed0212015-06-08 17:56:03 -070010509 /* We are not currently processing multipart data. */
Chris Fallin97b663a2015-01-09 16:15:22 -080010510 MULTIPART_INACTIVE = 0,
10511
Josh Habermane8ed0212015-06-08 17:56:03 -070010512 /* We are processing multipart data by accumulating it into a contiguous
10513 * buffer. */
Chris Fallin97b663a2015-01-09 16:15:22 -080010514 MULTIPART_ACCUMULATE = 1,
10515
Josh Habermane8ed0212015-06-08 17:56:03 -070010516 /* We are processing multipart data by pushing each part directly to the
10517 * current string handlers. */
Chris Fallin97b663a2015-01-09 16:15:22 -080010518 MULTIPART_PUSHEAGERLY = 2
10519};
10520
Josh Habermane8ed0212015-06-08 17:56:03 -070010521/* Start a multi-part text value where we accumulate the data for processing at
10522 * the end. */
Chris Fallin97b663a2015-01-09 16:15:22 -080010523static void multipart_startaccum(upb_json_parser *p) {
10524 assert_accumulate_empty(p);
10525 assert(p->multipart_state == MULTIPART_INACTIVE);
10526 p->multipart_state = MULTIPART_ACCUMULATE;
10527}
10528
Josh Habermane8ed0212015-06-08 17:56:03 -070010529/* Start a multi-part text value where we immediately push text data to a string
10530 * value with the given selector. */
Chris Fallin97b663a2015-01-09 16:15:22 -080010531static void multipart_start(upb_json_parser *p, upb_selector_t sel) {
10532 assert_accumulate_empty(p);
10533 assert(p->multipart_state == MULTIPART_INACTIVE);
10534 p->multipart_state = MULTIPART_PUSHEAGERLY;
10535 p->string_selector = sel;
10536}
10537
10538static bool multipart_text(upb_json_parser *p, const char *buf, size_t len,
10539 bool can_alias) {
10540 switch (p->multipart_state) {
10541 case MULTIPART_INACTIVE:
10542 upb_status_seterrmsg(
Josh Haberman181c7f22015-07-15 11:05:10 -070010543 &p->status, "Internal error: unexpected state MULTIPART_INACTIVE");
10544 upb_env_reporterror(p->env, &p->status);
Chris Fallin91473dc2014-12-12 15:58:26 -080010545 return false;
Chris Fallin97b663a2015-01-09 16:15:22 -080010546
10547 case MULTIPART_ACCUMULATE:
10548 if (!accumulate_append(p, buf, len, can_alias)) {
10549 return false;
10550 }
10551 break;
10552
10553 case MULTIPART_PUSHEAGERLY: {
10554 const upb_bufhandle *handle = can_alias ? p->handle : NULL;
10555 upb_sink_putstring(&p->top->sink, p->string_selector, buf, len, handle);
10556 break;
Chris Fallin91473dc2014-12-12 15:58:26 -080010557 }
Chris Fallin91473dc2014-12-12 15:58:26 -080010558 }
10559
10560 return true;
10561}
10562
Josh Habermane8ed0212015-06-08 17:56:03 -070010563/* Note: this invalidates the accumulate buffer! Call only after reading its
10564 * contents. */
Chris Fallin97b663a2015-01-09 16:15:22 -080010565static void multipart_end(upb_json_parser *p) {
10566 assert(p->multipart_state != MULTIPART_INACTIVE);
10567 p->multipart_state = MULTIPART_INACTIVE;
10568 accumulate_clear(p);
10569}
Chris Fallin91473dc2014-12-12 15:58:26 -080010570
Chris Fallin91473dc2014-12-12 15:58:26 -080010571
Chris Fallin97b663a2015-01-09 16:15:22 -080010572/* Input capture **************************************************************/
Chris Fallin91473dc2014-12-12 15:58:26 -080010573
Josh Habermane8ed0212015-06-08 17:56:03 -070010574/* Functionality for capturing a region of the input as text. Gracefully
10575 * handles the case where a buffer seam occurs in the middle of the captured
10576 * region. */
Chris Fallin97b663a2015-01-09 16:15:22 -080010577
10578static void capture_begin(upb_json_parser *p, const char *ptr) {
10579 assert(p->multipart_state != MULTIPART_INACTIVE);
10580 assert(p->capture == NULL);
10581 p->capture = ptr;
10582}
10583
10584static bool capture_end(upb_json_parser *p, const char *ptr) {
10585 assert(p->capture);
10586 if (multipart_text(p, p->capture, ptr - p->capture, true)) {
10587 p->capture = NULL;
Chris Fallin91473dc2014-12-12 15:58:26 -080010588 return true;
10589 } else {
Chris Fallin91473dc2014-12-12 15:58:26 -080010590 return false;
10591 }
Chris Fallin91473dc2014-12-12 15:58:26 -080010592}
10593
Josh Habermane8ed0212015-06-08 17:56:03 -070010594/* This is called at the end of each input buffer (ie. when we have hit a
10595 * buffer seam). If we are in the middle of capturing the input, this
10596 * processes the unprocessed capture region. */
Chris Fallin97b663a2015-01-09 16:15:22 -080010597static void capture_suspend(upb_json_parser *p, const char **ptr) {
10598 if (!p->capture) return;
10599
10600 if (multipart_text(p, p->capture, *ptr - p->capture, false)) {
Josh Habermane8ed0212015-06-08 17:56:03 -070010601 /* We use this as a signal that we were in the middle of capturing, and
10602 * that capturing should resume at the beginning of the next buffer.
10603 *
10604 * We can't use *ptr here, because we have no guarantee that this pointer
10605 * will be valid when we resume (if the underlying memory is freed, then
10606 * using the pointer at all, even to compare to NULL, is likely undefined
10607 * behavior). */
Chris Fallin97b663a2015-01-09 16:15:22 -080010608 p->capture = &suspend_capture;
10609 } else {
Josh Habermane8ed0212015-06-08 17:56:03 -070010610 /* Need to back up the pointer to the beginning of the capture, since
10611 * we were not able to actually preserve it. */
Chris Fallin97b663a2015-01-09 16:15:22 -080010612 *ptr = p->capture;
Chris Fallin91473dc2014-12-12 15:58:26 -080010613 }
10614}
10615
Chris Fallin97b663a2015-01-09 16:15:22 -080010616static void capture_resume(upb_json_parser *p, const char *ptr) {
10617 if (p->capture) {
10618 assert(p->capture == &suspend_capture);
10619 p->capture = ptr;
Chris Fallin91473dc2014-12-12 15:58:26 -080010620 }
Chris Fallin91473dc2014-12-12 15:58:26 -080010621}
10622
Chris Fallin97b663a2015-01-09 16:15:22 -080010623
10624/* Callbacks from the parser **************************************************/
10625
Josh Habermane8ed0212015-06-08 17:56:03 -070010626/* These are the functions called directly from the parser itself.
10627 * We define these in the same order as their declarations in the parser. */
Chris Fallin97b663a2015-01-09 16:15:22 -080010628
Chris Fallin91473dc2014-12-12 15:58:26 -080010629static char escape_char(char in) {
10630 switch (in) {
10631 case 'r': return '\r';
10632 case 't': return '\t';
10633 case 'n': return '\n';
10634 case 'f': return '\f';
10635 case 'b': return '\b';
10636 case '/': return '/';
10637 case '"': return '"';
10638 case '\\': return '\\';
10639 default:
10640 assert(0);
10641 return 'x';
10642 }
10643}
10644
Chris Fallin97b663a2015-01-09 16:15:22 -080010645static bool escape(upb_json_parser *p, const char *ptr) {
Chris Fallin91473dc2014-12-12 15:58:26 -080010646 char ch = escape_char(*ptr);
Chris Fallin97b663a2015-01-09 16:15:22 -080010647 return multipart_text(p, &ch, 1, false);
Chris Fallin91473dc2014-12-12 15:58:26 -080010648}
10649
Chris Fallin97b663a2015-01-09 16:15:22 -080010650static void start_hex(upb_json_parser *p) {
10651 p->digit = 0;
10652}
10653
10654static void hexdigit(upb_json_parser *p, const char *ptr) {
10655 char ch = *ptr;
10656
10657 p->digit <<= 4;
10658
Chris Fallin91473dc2014-12-12 15:58:26 -080010659 if (ch >= '0' && ch <= '9') {
Chris Fallin97b663a2015-01-09 16:15:22 -080010660 p->digit += (ch - '0');
Chris Fallin91473dc2014-12-12 15:58:26 -080010661 } else if (ch >= 'a' && ch <= 'f') {
Chris Fallin97b663a2015-01-09 16:15:22 -080010662 p->digit += ((ch - 'a') + 10);
Chris Fallin91473dc2014-12-12 15:58:26 -080010663 } else {
10664 assert(ch >= 'A' && ch <= 'F');
Chris Fallin97b663a2015-01-09 16:15:22 -080010665 p->digit += ((ch - 'A') + 10);
Chris Fallin91473dc2014-12-12 15:58:26 -080010666 }
10667}
10668
Chris Fallin97b663a2015-01-09 16:15:22 -080010669static bool end_hex(upb_json_parser *p) {
10670 uint32_t codepoint = p->digit;
Chris Fallin91473dc2014-12-12 15:58:26 -080010671
Josh Habermane8ed0212015-06-08 17:56:03 -070010672 /* emit the codepoint as UTF-8. */
10673 char utf8[3]; /* support \u0000 -- \uFFFF -- need only three bytes. */
Chris Fallin91473dc2014-12-12 15:58:26 -080010674 int length = 0;
10675 if (codepoint <= 0x7F) {
10676 utf8[0] = codepoint;
10677 length = 1;
10678 } else if (codepoint <= 0x07FF) {
10679 utf8[1] = (codepoint & 0x3F) | 0x80;
10680 codepoint >>= 6;
10681 utf8[0] = (codepoint & 0x1F) | 0xC0;
10682 length = 2;
10683 } else /* codepoint <= 0xFFFF */ {
10684 utf8[2] = (codepoint & 0x3F) | 0x80;
10685 codepoint >>= 6;
10686 utf8[1] = (codepoint & 0x3F) | 0x80;
10687 codepoint >>= 6;
10688 utf8[0] = (codepoint & 0x0F) | 0xE0;
10689 length = 3;
10690 }
Josh Habermane8ed0212015-06-08 17:56:03 -070010691 /* TODO(haberman): Handle high surrogates: if codepoint is a high surrogate
10692 * we have to wait for the next escape to get the full code point). */
Chris Fallin91473dc2014-12-12 15:58:26 -080010693
Chris Fallin97b663a2015-01-09 16:15:22 -080010694 return multipart_text(p, utf8, length, false);
Chris Fallin91473dc2014-12-12 15:58:26 -080010695}
10696
Chris Fallin97b663a2015-01-09 16:15:22 -080010697static void start_text(upb_json_parser *p, const char *ptr) {
10698 capture_begin(p, ptr);
10699}
10700
10701static bool end_text(upb_json_parser *p, const char *ptr) {
10702 return capture_end(p, ptr);
10703}
10704
10705static void start_number(upb_json_parser *p, const char *ptr) {
10706 multipart_startaccum(p);
10707 capture_begin(p, ptr);
10708}
10709
Chris Fallina5075922015-02-02 15:07:34 -080010710static bool parse_number(upb_json_parser *p);
10711
Chris Fallin97b663a2015-01-09 16:15:22 -080010712static bool end_number(upb_json_parser *p, const char *ptr) {
10713 if (!capture_end(p, ptr)) {
10714 return false;
10715 }
10716
Chris Fallina5075922015-02-02 15:07:34 -080010717 return parse_number(p);
10718}
10719
10720static bool parse_number(upb_json_parser *p) {
Josh Habermane8ed0212015-06-08 17:56:03 -070010721 size_t len;
10722 const char *buf;
10723 const char *myend;
10724 char *end;
10725
10726 /* strtol() and friends unfortunately do not support specifying the length of
10727 * the input string, so we need to force a copy into a NULL-terminated buffer. */
Chris Fallin97b663a2015-01-09 16:15:22 -080010728 if (!multipart_text(p, "\0", 1, false)) {
10729 return false;
10730 }
10731
Josh Habermane8ed0212015-06-08 17:56:03 -070010732 buf = accumulate_getptr(p, &len);
10733 myend = buf + len - 1; /* One for NULL. */
Chris Fallin97b663a2015-01-09 16:15:22 -080010734
Josh Habermane8ed0212015-06-08 17:56:03 -070010735 /* XXX: We are using strtol to parse integers, but this is wrong as even
10736 * integers can be represented as 1e6 (for example), which strtol can't
10737 * handle correctly.
10738 *
10739 * XXX: Also, we can't handle large integers properly because strto[u]ll
10740 * isn't in C89.
10741 *
10742 * XXX: Also, we don't properly check floats for overflow, since strtof
10743 * isn't in C89. */
Chris Fallin97b663a2015-01-09 16:15:22 -080010744 switch (upb_fielddef_type(p->top->f)) {
10745 case UPB_TYPE_ENUM:
10746 case UPB_TYPE_INT32: {
10747 long val = strtol(p->accumulated, &end, 0);
10748 if (val > INT32_MAX || val < INT32_MIN || errno == ERANGE || end != myend)
10749 goto err;
10750 else
10751 upb_sink_putint32(&p->top->sink, parser_getsel(p), val);
10752 break;
10753 }
10754 case UPB_TYPE_INT64: {
Josh Habermane8ed0212015-06-08 17:56:03 -070010755 long long val = strtol(p->accumulated, &end, 0);
Chris Fallin97b663a2015-01-09 16:15:22 -080010756 if (val > INT64_MAX || val < INT64_MIN || errno == ERANGE || end != myend)
10757 goto err;
10758 else
10759 upb_sink_putint64(&p->top->sink, parser_getsel(p), val);
10760 break;
10761 }
10762 case UPB_TYPE_UINT32: {
10763 unsigned long val = strtoul(p->accumulated, &end, 0);
10764 if (val > UINT32_MAX || errno == ERANGE || end != myend)
10765 goto err;
10766 else
10767 upb_sink_putuint32(&p->top->sink, parser_getsel(p), val);
10768 break;
10769 }
10770 case UPB_TYPE_UINT64: {
Josh Habermane8ed0212015-06-08 17:56:03 -070010771 unsigned long long val = strtoul(p->accumulated, &end, 0);
Chris Fallin97b663a2015-01-09 16:15:22 -080010772 if (val > UINT64_MAX || errno == ERANGE || end != myend)
10773 goto err;
10774 else
10775 upb_sink_putuint64(&p->top->sink, parser_getsel(p), val);
10776 break;
10777 }
10778 case UPB_TYPE_DOUBLE: {
10779 double val = strtod(p->accumulated, &end);
10780 if (errno == ERANGE || end != myend)
10781 goto err;
10782 else
10783 upb_sink_putdouble(&p->top->sink, parser_getsel(p), val);
10784 break;
10785 }
10786 case UPB_TYPE_FLOAT: {
Josh Habermane8ed0212015-06-08 17:56:03 -070010787 float val = strtod(p->accumulated, &end);
Chris Fallin97b663a2015-01-09 16:15:22 -080010788 if (errno == ERANGE || end != myend)
10789 goto err;
10790 else
10791 upb_sink_putfloat(&p->top->sink, parser_getsel(p), val);
10792 break;
10793 }
10794 default:
10795 assert(false);
10796 }
10797
10798 multipart_end(p);
Chris Fallina5075922015-02-02 15:07:34 -080010799
Chris Fallin97b663a2015-01-09 16:15:22 -080010800 return true;
10801
10802err:
Josh Haberman181c7f22015-07-15 11:05:10 -070010803 upb_status_seterrf(&p->status, "error parsing number: %s", buf);
10804 upb_env_reporterror(p->env, &p->status);
Chris Fallin97b663a2015-01-09 16:15:22 -080010805 multipart_end(p);
10806 return false;
10807}
10808
10809static bool parser_putbool(upb_json_parser *p, bool val) {
Josh Habermane8ed0212015-06-08 17:56:03 -070010810 bool ok;
10811
Chris Fallin97b663a2015-01-09 16:15:22 -080010812 if (upb_fielddef_type(p->top->f) != UPB_TYPE_BOOL) {
Josh Haberman181c7f22015-07-15 11:05:10 -070010813 upb_status_seterrf(&p->status,
Chris Fallin97b663a2015-01-09 16:15:22 -080010814 "Boolean value specified for non-bool field: %s",
10815 upb_fielddef_name(p->top->f));
Josh Haberman181c7f22015-07-15 11:05:10 -070010816 upb_env_reporterror(p->env, &p->status);
Chris Fallin97b663a2015-01-09 16:15:22 -080010817 return false;
10818 }
10819
Josh Habermane8ed0212015-06-08 17:56:03 -070010820 ok = upb_sink_putbool(&p->top->sink, parser_getsel(p), val);
Chris Fallin97b663a2015-01-09 16:15:22 -080010821 UPB_ASSERT_VAR(ok, ok);
Chris Fallina5075922015-02-02 15:07:34 -080010822
Chris Fallin97b663a2015-01-09 16:15:22 -080010823 return true;
10824}
10825
10826static bool start_stringval(upb_json_parser *p) {
10827 assert(p->top->f);
10828
10829 if (upb_fielddef_isstring(p->top->f)) {
Josh Habermane8ed0212015-06-08 17:56:03 -070010830 upb_jsonparser_frame *inner;
10831 upb_selector_t sel;
10832
Chris Fallin97b663a2015-01-09 16:15:22 -080010833 if (!check_stack(p)) return false;
10834
Josh Habermane8ed0212015-06-08 17:56:03 -070010835 /* Start a new parser frame: parser frames correspond one-to-one with
10836 * handler frames, and string events occur in a sub-frame. */
10837 inner = p->top + 1;
10838 sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSTR);
Chris Fallin97b663a2015-01-09 16:15:22 -080010839 upb_sink_startstr(&p->top->sink, sel, 0, &inner->sink);
10840 inner->m = p->top->m;
10841 inner->f = p->top->f;
Josh Haberman78da6662016-01-13 19:05:43 -080010842 inner->name_table = NULL;
Chris Fallina5075922015-02-02 15:07:34 -080010843 inner->is_map = false;
10844 inner->is_mapentry = false;
Chris Fallin97b663a2015-01-09 16:15:22 -080010845 p->top = inner;
10846
10847 if (upb_fielddef_type(p->top->f) == UPB_TYPE_STRING) {
Josh Habermane8ed0212015-06-08 17:56:03 -070010848 /* For STRING fields we push data directly to the handlers as it is
10849 * parsed. We don't do this yet for BYTES fields, because our base64
10850 * decoder is not streaming.
10851 *
10852 * TODO(haberman): make base64 decoding streaming also. */
Chris Fallin97b663a2015-01-09 16:15:22 -080010853 multipart_start(p, getsel_for_handlertype(p, UPB_HANDLER_STRING));
10854 return true;
10855 } else {
10856 multipart_startaccum(p);
10857 return true;
10858 }
10859 } else if (upb_fielddef_type(p->top->f) == UPB_TYPE_ENUM) {
Josh Habermane8ed0212015-06-08 17:56:03 -070010860 /* No need to push a frame -- symbolic enum names in quotes remain in the
10861 * current parser frame.
10862 *
10863 * Enum string values must accumulate so we can look up the value in a table
10864 * once it is complete. */
Chris Fallin97b663a2015-01-09 16:15:22 -080010865 multipart_startaccum(p);
10866 return true;
10867 } else {
Josh Haberman181c7f22015-07-15 11:05:10 -070010868 upb_status_seterrf(&p->status,
Chris Fallin97b663a2015-01-09 16:15:22 -080010869 "String specified for non-string/non-enum field: %s",
10870 upb_fielddef_name(p->top->f));
Josh Haberman181c7f22015-07-15 11:05:10 -070010871 upb_env_reporterror(p->env, &p->status);
Chris Fallin97b663a2015-01-09 16:15:22 -080010872 return false;
10873 }
10874}
10875
10876static bool end_stringval(upb_json_parser *p) {
10877 bool ok = true;
10878
10879 switch (upb_fielddef_type(p->top->f)) {
10880 case UPB_TYPE_BYTES:
10881 if (!base64_push(p, getsel_for_handlertype(p, UPB_HANDLER_STRING),
10882 p->accumulated, p->accumulated_len)) {
10883 return false;
10884 }
Josh Habermane8ed0212015-06-08 17:56:03 -070010885 /* Fall through. */
Chris Fallin97b663a2015-01-09 16:15:22 -080010886
10887 case UPB_TYPE_STRING: {
10888 upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR);
10889 upb_sink_endstr(&p->top->sink, sel);
10890 p->top--;
10891 break;
10892 }
10893
10894 case UPB_TYPE_ENUM: {
Josh Habermane8ed0212015-06-08 17:56:03 -070010895 /* Resolve enum symbolic name to integer value. */
Chris Fallin97b663a2015-01-09 16:15:22 -080010896 const upb_enumdef *enumdef =
10897 (const upb_enumdef*)upb_fielddef_subdef(p->top->f);
10898
10899 size_t len;
10900 const char *buf = accumulate_getptr(p, &len);
10901
10902 int32_t int_val = 0;
10903 ok = upb_enumdef_ntoi(enumdef, buf, len, &int_val);
10904
10905 if (ok) {
10906 upb_selector_t sel = parser_getsel(p);
10907 upb_sink_putint32(&p->top->sink, sel, int_val);
10908 } else {
Josh Haberman181c7f22015-07-15 11:05:10 -070010909 upb_status_seterrf(&p->status, "Enum value unknown: '%.*s'", len, buf);
10910 upb_env_reporterror(p->env, &p->status);
Chris Fallin97b663a2015-01-09 16:15:22 -080010911 }
10912
10913 break;
10914 }
10915
10916 default:
10917 assert(false);
Josh Haberman181c7f22015-07-15 11:05:10 -070010918 upb_status_seterrmsg(&p->status, "Internal error in JSON decoder");
10919 upb_env_reporterror(p->env, &p->status);
Chris Fallin97b663a2015-01-09 16:15:22 -080010920 ok = false;
10921 break;
10922 }
10923
10924 multipart_end(p);
Chris Fallina5075922015-02-02 15:07:34 -080010925
Chris Fallin97b663a2015-01-09 16:15:22 -080010926 return ok;
10927}
10928
10929static void start_member(upb_json_parser *p) {
10930 assert(!p->top->f);
10931 multipart_startaccum(p);
10932}
10933
Josh Habermane8ed0212015-06-08 17:56:03 -070010934/* Helper: invoked during parse_mapentry() to emit the mapentry message's key
10935 * field based on the current contents of the accumulate buffer. */
Chris Fallina5075922015-02-02 15:07:34 -080010936static bool parse_mapentry_key(upb_json_parser *p) {
10937
Chris Fallin97b663a2015-01-09 16:15:22 -080010938 size_t len;
10939 const char *buf = accumulate_getptr(p, &len);
10940
Josh Habermane8ed0212015-06-08 17:56:03 -070010941 /* Emit the key field. We do a bit of ad-hoc parsing here because the
10942 * parser state machine has already decided that this is a string field
10943 * name, and we are reinterpreting it as some arbitrary key type. In
10944 * particular, integer and bool keys are quoted, so we need to parse the
10945 * quoted string contents here. */
Chris Fallin97b663a2015-01-09 16:15:22 -080010946
Chris Fallina5075922015-02-02 15:07:34 -080010947 p->top->f = upb_msgdef_itof(p->top->m, UPB_MAPENTRY_KEY);
10948 if (p->top->f == NULL) {
Josh Haberman181c7f22015-07-15 11:05:10 -070010949 upb_status_seterrmsg(&p->status, "mapentry message has no key");
10950 upb_env_reporterror(p->env, &p->status);
Chris Fallin97b663a2015-01-09 16:15:22 -080010951 return false;
10952 }
Chris Fallina5075922015-02-02 15:07:34 -080010953 switch (upb_fielddef_type(p->top->f)) {
10954 case UPB_TYPE_INT32:
10955 case UPB_TYPE_INT64:
10956 case UPB_TYPE_UINT32:
10957 case UPB_TYPE_UINT64:
Josh Habermane8ed0212015-06-08 17:56:03 -070010958 /* Invoke end_number. The accum buffer has the number's text already. */
Chris Fallina5075922015-02-02 15:07:34 -080010959 if (!parse_number(p)) {
10960 return false;
10961 }
10962 break;
10963 case UPB_TYPE_BOOL:
10964 if (len == 4 && !strncmp(buf, "true", 4)) {
10965 if (!parser_putbool(p, true)) {
10966 return false;
10967 }
10968 } else if (len == 5 && !strncmp(buf, "false", 5)) {
10969 if (!parser_putbool(p, false)) {
10970 return false;
10971 }
10972 } else {
Josh Haberman181c7f22015-07-15 11:05:10 -070010973 upb_status_seterrmsg(&p->status,
Chris Fallina5075922015-02-02 15:07:34 -080010974 "Map bool key not 'true' or 'false'");
Josh Haberman181c7f22015-07-15 11:05:10 -070010975 upb_env_reporterror(p->env, &p->status);
Chris Fallina5075922015-02-02 15:07:34 -080010976 return false;
10977 }
10978 multipart_end(p);
10979 break;
10980 case UPB_TYPE_STRING:
10981 case UPB_TYPE_BYTES: {
10982 upb_sink subsink;
10983 upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSTR);
10984 upb_sink_startstr(&p->top->sink, sel, len, &subsink);
10985 sel = getsel_for_handlertype(p, UPB_HANDLER_STRING);
10986 upb_sink_putstring(&subsink, sel, buf, len, NULL);
10987 sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR);
10988 upb_sink_endstr(&subsink, sel);
10989 multipart_end(p);
10990 break;
10991 }
10992 default:
Josh Haberman181c7f22015-07-15 11:05:10 -070010993 upb_status_seterrmsg(&p->status, "Invalid field type for map key");
10994 upb_env_reporterror(p->env, &p->status);
Chris Fallina5075922015-02-02 15:07:34 -080010995 return false;
10996 }
Chris Fallin97b663a2015-01-09 16:15:22 -080010997
10998 return true;
10999}
11000
Josh Habermane8ed0212015-06-08 17:56:03 -070011001/* Helper: emit one map entry (as a submessage in the map field sequence). This
11002 * is invoked from end_membername(), at the end of the map entry's key string,
11003 * with the map key in the accumulate buffer. It parses the key from that
11004 * buffer, emits the handler calls to start the mapentry submessage (setting up
11005 * its subframe in the process), and sets up state in the subframe so that the
11006 * value parser (invoked next) will emit the mapentry's value field and then
11007 * end the mapentry message. */
Chris Fallina5075922015-02-02 15:07:34 -080011008
11009static bool handle_mapentry(upb_json_parser *p) {
Josh Habermane8ed0212015-06-08 17:56:03 -070011010 const upb_fielddef *mapfield;
11011 const upb_msgdef *mapentrymsg;
11012 upb_jsonparser_frame *inner;
11013 upb_selector_t sel;
11014
11015 /* Map entry: p->top->sink is the seq frame, so we need to start a frame
11016 * for the mapentry itself, and then set |f| in that frame so that the map
11017 * value field is parsed, and also set a flag to end the frame after the
11018 * map-entry value is parsed. */
Chris Fallina5075922015-02-02 15:07:34 -080011019 if (!check_stack(p)) return false;
11020
Josh Habermane8ed0212015-06-08 17:56:03 -070011021 mapfield = p->top->mapfield;
11022 mapentrymsg = upb_fielddef_msgsubdef(mapfield);
Chris Fallina5075922015-02-02 15:07:34 -080011023
Josh Habermane8ed0212015-06-08 17:56:03 -070011024 inner = p->top + 1;
Chris Fallina5075922015-02-02 15:07:34 -080011025 p->top->f = mapfield;
Josh Habermane8ed0212015-06-08 17:56:03 -070011026 sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSUBMSG);
Chris Fallina5075922015-02-02 15:07:34 -080011027 upb_sink_startsubmsg(&p->top->sink, sel, &inner->sink);
11028 inner->m = mapentrymsg;
Josh Haberman78da6662016-01-13 19:05:43 -080011029 inner->name_table = NULL;
Chris Fallina5075922015-02-02 15:07:34 -080011030 inner->mapfield = mapfield;
11031 inner->is_map = false;
11032
Josh Habermane8ed0212015-06-08 17:56:03 -070011033 /* Don't set this to true *yet* -- we reuse parsing handlers below to push
11034 * the key field value to the sink, and these handlers will pop the frame
11035 * if they see is_mapentry (when invoked by the parser state machine, they
11036 * would have just seen the map-entry value, not key). */
Chris Fallina5075922015-02-02 15:07:34 -080011037 inner->is_mapentry = false;
11038 p->top = inner;
11039
Josh Habermane8ed0212015-06-08 17:56:03 -070011040 /* send STARTMSG in submsg frame. */
Chris Fallina5075922015-02-02 15:07:34 -080011041 upb_sink_startmsg(&p->top->sink);
11042
11043 parse_mapentry_key(p);
11044
Josh Habermane8ed0212015-06-08 17:56:03 -070011045 /* Set up the value field to receive the map-entry value. */
Chris Fallina5075922015-02-02 15:07:34 -080011046 p->top->f = upb_msgdef_itof(p->top->m, UPB_MAPENTRY_VALUE);
Josh Habermane8ed0212015-06-08 17:56:03 -070011047 p->top->is_mapentry = true; /* set up to pop frame after value is parsed. */
Chris Fallina5075922015-02-02 15:07:34 -080011048 p->top->mapfield = mapfield;
11049 if (p->top->f == NULL) {
Josh Haberman181c7f22015-07-15 11:05:10 -070011050 upb_status_seterrmsg(&p->status, "mapentry message has no value");
11051 upb_env_reporterror(p->env, &p->status);
Chris Fallina5075922015-02-02 15:07:34 -080011052 return false;
11053 }
11054
11055 return true;
11056}
11057
11058static bool end_membername(upb_json_parser *p) {
11059 assert(!p->top->f);
11060
11061 if (p->top->is_map) {
11062 return handle_mapentry(p);
11063 } else {
11064 size_t len;
11065 const char *buf = accumulate_getptr(p, &len);
Josh Haberman78da6662016-01-13 19:05:43 -080011066 upb_value v;
Chris Fallina5075922015-02-02 15:07:34 -080011067
Josh Haberman78da6662016-01-13 19:05:43 -080011068 if (upb_strtable_lookup2(p->top->name_table, buf, len, &v)) {
11069 p->top->f = upb_value_getconstptr(v);
11070 multipart_end(p);
11071
11072 return true;
11073 } else {
Josh Habermane8ed0212015-06-08 17:56:03 -070011074 /* TODO(haberman): Ignore unknown fields if requested/configured to do
11075 * so. */
Josh Haberman181c7f22015-07-15 11:05:10 -070011076 upb_status_seterrf(&p->status, "No such field: %.*s\n", (int)len, buf);
11077 upb_env_reporterror(p->env, &p->status);
Chris Fallina5075922015-02-02 15:07:34 -080011078 return false;
11079 }
Chris Fallina5075922015-02-02 15:07:34 -080011080 }
11081}
11082
11083static void end_member(upb_json_parser *p) {
Josh Habermane8ed0212015-06-08 17:56:03 -070011084 /* If we just parsed a map-entry value, end that frame too. */
Chris Fallina5075922015-02-02 15:07:34 -080011085 if (p->top->is_mapentry) {
Chris Fallina5075922015-02-02 15:07:34 -080011086 upb_status s = UPB_STATUS_INIT;
Chris Fallina5075922015-02-02 15:07:34 -080011087 upb_selector_t sel;
Josh Habermane8ed0212015-06-08 17:56:03 -070011088 bool ok;
11089 const upb_fielddef *mapfield;
11090
11091 assert(p->top > p->stack);
11092 /* send ENDMSG on submsg. */
11093 upb_sink_endmsg(&p->top->sink, &s);
11094 mapfield = p->top->mapfield;
11095
11096 /* send ENDSUBMSG in repeated-field-of-mapentries frame. */
11097 p->top--;
11098 ok = upb_handlers_getselector(mapfield, UPB_HANDLER_ENDSUBMSG, &sel);
Chris Fallina5075922015-02-02 15:07:34 -080011099 UPB_ASSERT_VAR(ok, ok);
11100 upb_sink_endsubmsg(&p->top->sink, sel);
11101 }
11102
11103 p->top->f = NULL;
11104}
Chris Fallin97b663a2015-01-09 16:15:22 -080011105
11106static bool start_subobject(upb_json_parser *p) {
11107 assert(p->top->f);
11108
Chris Fallina5075922015-02-02 15:07:34 -080011109 if (upb_fielddef_ismap(p->top->f)) {
Josh Habermane8ed0212015-06-08 17:56:03 -070011110 upb_jsonparser_frame *inner;
11111 upb_selector_t sel;
11112
11113 /* Beginning of a map. Start a new parser frame in a repeated-field
11114 * context. */
Chris Fallina5075922015-02-02 15:07:34 -080011115 if (!check_stack(p)) return false;
11116
Josh Habermane8ed0212015-06-08 17:56:03 -070011117 inner = p->top + 1;
11118 sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSEQ);
Chris Fallina5075922015-02-02 15:07:34 -080011119 upb_sink_startseq(&p->top->sink, sel, &inner->sink);
11120 inner->m = upb_fielddef_msgsubdef(p->top->f);
Josh Haberman78da6662016-01-13 19:05:43 -080011121 inner->name_table = NULL;
Chris Fallina5075922015-02-02 15:07:34 -080011122 inner->mapfield = p->top->f;
11123 inner->f = NULL;
11124 inner->is_map = true;
11125 inner->is_mapentry = false;
11126 p->top = inner;
11127
11128 return true;
11129 } else if (upb_fielddef_issubmsg(p->top->f)) {
Josh Habermane8ed0212015-06-08 17:56:03 -070011130 upb_jsonparser_frame *inner;
11131 upb_selector_t sel;
11132
11133 /* Beginning of a subobject. Start a new parser frame in the submsg
11134 * context. */
Chris Fallina5075922015-02-02 15:07:34 -080011135 if (!check_stack(p)) return false;
11136
Josh Habermane8ed0212015-06-08 17:56:03 -070011137 inner = p->top + 1;
Chris Fallina5075922015-02-02 15:07:34 -080011138
Josh Habermane8ed0212015-06-08 17:56:03 -070011139 sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSUBMSG);
Chris Fallina5075922015-02-02 15:07:34 -080011140 upb_sink_startsubmsg(&p->top->sink, sel, &inner->sink);
11141 inner->m = upb_fielddef_msgsubdef(p->top->f);
Josh Haberman78da6662016-01-13 19:05:43 -080011142 set_name_table(p, inner);
Chris Fallina5075922015-02-02 15:07:34 -080011143 inner->f = NULL;
11144 inner->is_map = false;
11145 inner->is_mapentry = false;
11146 p->top = inner;
11147
11148 return true;
11149 } else {
Josh Haberman181c7f22015-07-15 11:05:10 -070011150 upb_status_seterrf(&p->status,
Chris Fallin97b663a2015-01-09 16:15:22 -080011151 "Object specified for non-message/group field: %s",
11152 upb_fielddef_name(p->top->f));
Josh Haberman181c7f22015-07-15 11:05:10 -070011153 upb_env_reporterror(p->env, &p->status);
Chris Fallin97b663a2015-01-09 16:15:22 -080011154 return false;
11155 }
Chris Fallin97b663a2015-01-09 16:15:22 -080011156}
11157
11158static void end_subobject(upb_json_parser *p) {
Chris Fallina5075922015-02-02 15:07:34 -080011159 if (p->top->is_map) {
Josh Habermane8ed0212015-06-08 17:56:03 -070011160 upb_selector_t sel;
Chris Fallina5075922015-02-02 15:07:34 -080011161 p->top--;
Josh Habermane8ed0212015-06-08 17:56:03 -070011162 sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSEQ);
Chris Fallina5075922015-02-02 15:07:34 -080011163 upb_sink_endseq(&p->top->sink, sel);
11164 } else {
Josh Habermane8ed0212015-06-08 17:56:03 -070011165 upb_selector_t sel;
Chris Fallina5075922015-02-02 15:07:34 -080011166 p->top--;
Josh Habermane8ed0212015-06-08 17:56:03 -070011167 sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSUBMSG);
Chris Fallina5075922015-02-02 15:07:34 -080011168 upb_sink_endsubmsg(&p->top->sink, sel);
11169 }
Chris Fallin97b663a2015-01-09 16:15:22 -080011170}
11171
11172static bool start_array(upb_json_parser *p) {
Josh Habermane8ed0212015-06-08 17:56:03 -070011173 upb_jsonparser_frame *inner;
11174 upb_selector_t sel;
11175
Chris Fallin97b663a2015-01-09 16:15:22 -080011176 assert(p->top->f);
11177
11178 if (!upb_fielddef_isseq(p->top->f)) {
Josh Haberman181c7f22015-07-15 11:05:10 -070011179 upb_status_seterrf(&p->status,
Chris Fallin97b663a2015-01-09 16:15:22 -080011180 "Array specified for non-repeated field: %s",
11181 upb_fielddef_name(p->top->f));
Josh Haberman181c7f22015-07-15 11:05:10 -070011182 upb_env_reporterror(p->env, &p->status);
Chris Fallin97b663a2015-01-09 16:15:22 -080011183 return false;
11184 }
11185
11186 if (!check_stack(p)) return false;
11187
Josh Habermane8ed0212015-06-08 17:56:03 -070011188 inner = p->top + 1;
11189 sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSEQ);
Chris Fallin97b663a2015-01-09 16:15:22 -080011190 upb_sink_startseq(&p->top->sink, sel, &inner->sink);
11191 inner->m = p->top->m;
Josh Haberman78da6662016-01-13 19:05:43 -080011192 inner->name_table = NULL;
Chris Fallin97b663a2015-01-09 16:15:22 -080011193 inner->f = p->top->f;
Chris Fallina5075922015-02-02 15:07:34 -080011194 inner->is_map = false;
11195 inner->is_mapentry = false;
Chris Fallin97b663a2015-01-09 16:15:22 -080011196 p->top = inner;
11197
11198 return true;
11199}
11200
11201static void end_array(upb_json_parser *p) {
Josh Habermane8ed0212015-06-08 17:56:03 -070011202 upb_selector_t sel;
11203
Chris Fallin97b663a2015-01-09 16:15:22 -080011204 assert(p->top > p->stack);
11205
11206 p->top--;
Josh Habermane8ed0212015-06-08 17:56:03 -070011207 sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSEQ);
Chris Fallin97b663a2015-01-09 16:15:22 -080011208 upb_sink_endseq(&p->top->sink, sel);
11209}
11210
11211static void start_object(upb_json_parser *p) {
Chris Fallina5075922015-02-02 15:07:34 -080011212 if (!p->top->is_map) {
11213 upb_sink_startmsg(&p->top->sink);
11214 }
Chris Fallin97b663a2015-01-09 16:15:22 -080011215}
11216
11217static void end_object(upb_json_parser *p) {
Chris Fallina5075922015-02-02 15:07:34 -080011218 if (!p->top->is_map) {
11219 upb_status status;
Josh Haberman181c7f22015-07-15 11:05:10 -070011220 upb_status_clear(&status);
Chris Fallina5075922015-02-02 15:07:34 -080011221 upb_sink_endmsg(&p->top->sink, &status);
Josh Haberman181c7f22015-07-15 11:05:10 -070011222 if (!upb_ok(&status)) {
11223 upb_env_reporterror(p->env, &status);
11224 }
Chris Fallina5075922015-02-02 15:07:34 -080011225 }
Chris Fallin97b663a2015-01-09 16:15:22 -080011226}
11227
11228
Chris Fallin91473dc2014-12-12 15:58:26 -080011229#define CHECK_RETURN_TOP(x) if (!(x)) goto error
11230
Chris Fallin97b663a2015-01-09 16:15:22 -080011231
11232/* The actual parser **********************************************************/
11233
Josh Habermane8ed0212015-06-08 17:56:03 -070011234/* What follows is the Ragel parser itself. The language is specified in Ragel
11235 * and the actions call our C functions above.
11236 *
11237 * Ragel has an extensive set of functionality, and we use only a small part of
11238 * it. There are many action types but we only use a few:
11239 *
11240 * ">" -- transition into a machine
11241 * "%" -- transition out of a machine
11242 * "@" -- transition into a final state of a machine.
11243 *
11244 * "@" transitions are tricky because a machine can transition into a final
11245 * state repeatedly. But in some cases we know this can't happen, for example
11246 * a string which is delimited by a final '"' can only transition into its
11247 * final state once, when the closing '"' is seen. */
Chris Fallin91473dc2014-12-12 15:58:26 -080011248
Chris Fallin97b663a2015-01-09 16:15:22 -080011249
Josh Haberman78da6662016-01-13 19:05:43 -080011250#line 1246 "upb/json/parser.rl"
Chris Fallin91473dc2014-12-12 15:58:26 -080011251
11252
11253
Josh Haberman78da6662016-01-13 19:05:43 -080011254#line 1158 "upb/json/parser.c"
Chris Fallin91473dc2014-12-12 15:58:26 -080011255static const char _json_actions[] = {
11256 0, 1, 0, 1, 2, 1, 3, 1,
Chris Fallin97b663a2015-01-09 16:15:22 -080011257 5, 1, 6, 1, 7, 1, 8, 1,
11258 10, 1, 12, 1, 13, 1, 14, 1,
11259 15, 1, 16, 1, 17, 1, 21, 1,
11260 25, 1, 27, 2, 3, 8, 2, 4,
11261 5, 2, 6, 2, 2, 6, 8, 2,
11262 11, 9, 2, 13, 15, 2, 14, 15,
11263 2, 18, 1, 2, 19, 27, 2, 20,
11264 9, 2, 22, 27, 2, 23, 27, 2,
11265 24, 27, 2, 26, 27, 3, 14, 11,
11266 9
Chris Fallin91473dc2014-12-12 15:58:26 -080011267};
11268
11269static const unsigned char _json_key_offsets[] = {
Chris Fallin97b663a2015-01-09 16:15:22 -080011270 0, 0, 4, 9, 14, 15, 19, 24,
11271 29, 34, 38, 42, 45, 48, 50, 54,
11272 58, 60, 62, 67, 69, 71, 80, 86,
11273 92, 98, 104, 106, 115, 116, 116, 116,
11274 121, 126, 131, 132, 133, 134, 135, 135,
11275 136, 137, 138, 138, 139, 140, 141, 141,
11276 146, 151, 152, 156, 161, 166, 171, 175,
11277 175, 178, 178, 178
Chris Fallin91473dc2014-12-12 15:58:26 -080011278};
11279
11280static const char _json_trans_keys[] = {
11281 32, 123, 9, 13, 32, 34, 125, 9,
Chris Fallin97b663a2015-01-09 16:15:22 -080011282 13, 32, 34, 125, 9, 13, 34, 32,
11283 58, 9, 13, 32, 93, 125, 9, 13,
11284 32, 44, 125, 9, 13, 32, 44, 125,
11285 9, 13, 32, 34, 9, 13, 45, 48,
11286 49, 57, 48, 49, 57, 46, 69, 101,
11287 48, 57, 69, 101, 48, 57, 43, 45,
11288 48, 57, 48, 57, 48, 57, 46, 69,
11289 101, 48, 57, 34, 92, 34, 92, 34,
11290 47, 92, 98, 102, 110, 114, 116, 117,
11291 48, 57, 65, 70, 97, 102, 48, 57,
11292 65, 70, 97, 102, 48, 57, 65, 70,
11293 97, 102, 48, 57, 65, 70, 97, 102,
11294 34, 92, 34, 45, 91, 102, 110, 116,
11295 123, 48, 57, 34, 32, 93, 125, 9,
11296 13, 32, 44, 93, 9, 13, 32, 93,
11297 125, 9, 13, 97, 108, 115, 101, 117,
11298 108, 108, 114, 117, 101, 32, 34, 125,
11299 9, 13, 32, 34, 125, 9, 13, 34,
11300 32, 58, 9, 13, 32, 93, 125, 9,
11301 13, 32, 44, 125, 9, 13, 32, 44,
11302 125, 9, 13, 32, 34, 9, 13, 32,
11303 9, 13, 0
Chris Fallin91473dc2014-12-12 15:58:26 -080011304};
11305
11306static const char _json_single_lengths[] = {
Chris Fallin97b663a2015-01-09 16:15:22 -080011307 0, 2, 3, 3, 1, 2, 3, 3,
Chris Fallin91473dc2014-12-12 15:58:26 -080011308 3, 2, 2, 1, 3, 0, 2, 2,
11309 0, 0, 3, 2, 2, 9, 0, 0,
Chris Fallin97b663a2015-01-09 16:15:22 -080011310 0, 0, 2, 7, 1, 0, 0, 3,
11311 3, 3, 1, 1, 1, 1, 0, 1,
Chris Fallin91473dc2014-12-12 15:58:26 -080011312 1, 1, 0, 1, 1, 1, 0, 3,
Chris Fallin97b663a2015-01-09 16:15:22 -080011313 3, 1, 2, 3, 3, 3, 2, 0,
Chris Fallin91473dc2014-12-12 15:58:26 -080011314 1, 0, 0, 0
11315};
11316
11317static const char _json_range_lengths[] = {
Chris Fallin97b663a2015-01-09 16:15:22 -080011318 0, 1, 1, 1, 0, 1, 1, 1,
Chris Fallin91473dc2014-12-12 15:58:26 -080011319 1, 1, 1, 1, 0, 1, 1, 1,
11320 1, 1, 1, 0, 0, 0, 3, 3,
Chris Fallin97b663a2015-01-09 16:15:22 -080011321 3, 3, 0, 1, 0, 0, 0, 1,
11322 1, 1, 0, 0, 0, 0, 0, 0,
Chris Fallin91473dc2014-12-12 15:58:26 -080011323 0, 0, 0, 0, 0, 0, 0, 1,
Chris Fallin97b663a2015-01-09 16:15:22 -080011324 1, 0, 1, 1, 1, 1, 1, 0,
Chris Fallin91473dc2014-12-12 15:58:26 -080011325 1, 0, 0, 0
11326};
11327
11328static const short _json_index_offsets[] = {
Chris Fallin97b663a2015-01-09 16:15:22 -080011329 0, 0, 4, 9, 14, 16, 20, 25,
11330 30, 35, 39, 43, 46, 50, 52, 56,
11331 60, 62, 64, 69, 72, 75, 85, 89,
11332 93, 97, 101, 104, 113, 115, 116, 117,
11333 122, 127, 132, 134, 136, 138, 140, 141,
11334 143, 145, 147, 148, 150, 152, 154, 155,
11335 160, 165, 167, 171, 176, 181, 186, 190,
11336 191, 194, 195, 196
Chris Fallin91473dc2014-12-12 15:58:26 -080011337};
11338
11339static const char _json_indicies[] = {
11340 0, 2, 0, 1, 3, 4, 5, 3,
Chris Fallin97b663a2015-01-09 16:15:22 -080011341 1, 6, 7, 8, 6, 1, 9, 1,
11342 10, 11, 10, 1, 11, 1, 1, 11,
11343 12, 13, 14, 15, 13, 1, 16, 17,
11344 8, 16, 1, 17, 7, 17, 1, 18,
11345 19, 20, 1, 19, 20, 1, 22, 23,
11346 23, 21, 24, 1, 23, 23, 24, 21,
11347 25, 25, 26, 1, 26, 1, 26, 21,
11348 22, 23, 23, 20, 21, 28, 29, 27,
11349 31, 32, 30, 33, 33, 33, 33, 33,
11350 33, 33, 33, 34, 1, 35, 35, 35,
11351 1, 36, 36, 36, 1, 37, 37, 37,
11352 1, 38, 38, 38, 1, 40, 41, 39,
11353 42, 43, 44, 45, 46, 47, 48, 43,
11354 1, 49, 1, 50, 51, 53, 54, 1,
Chris Fallin91473dc2014-12-12 15:58:26 -080011355 53, 52, 55, 56, 54, 55, 1, 56,
Chris Fallin97b663a2015-01-09 16:15:22 -080011356 1, 1, 56, 52, 57, 1, 58, 1,
11357 59, 1, 60, 1, 61, 62, 1, 63,
11358 1, 64, 1, 65, 66, 1, 67, 1,
11359 68, 1, 69, 70, 71, 72, 70, 1,
11360 73, 74, 75, 73, 1, 76, 1, 77,
11361 78, 77, 1, 78, 1, 1, 78, 79,
11362 80, 81, 82, 80, 1, 83, 84, 75,
11363 83, 1, 84, 74, 84, 1, 85, 86,
11364 86, 1, 1, 1, 1, 0
Chris Fallin91473dc2014-12-12 15:58:26 -080011365};
11366
11367static const char _json_trans_targs[] = {
11368 1, 0, 2, 3, 4, 56, 3, 4,
Chris Fallin97b663a2015-01-09 16:15:22 -080011369 56, 5, 5, 6, 7, 8, 9, 56,
11370 8, 9, 11, 12, 18, 57, 13, 15,
11371 14, 16, 17, 20, 58, 21, 20, 58,
11372 21, 19, 22, 23, 24, 25, 26, 20,
11373 58, 21, 28, 30, 31, 34, 39, 43,
11374 47, 29, 59, 59, 32, 31, 29, 32,
11375 33, 35, 36, 37, 38, 59, 40, 41,
11376 42, 59, 44, 45, 46, 59, 48, 49,
11377 55, 48, 49, 55, 50, 50, 51, 52,
11378 53, 54, 55, 53, 54, 59, 56
Chris Fallin91473dc2014-12-12 15:58:26 -080011379};
11380
11381static const char _json_trans_actions[] = {
Chris Fallin97b663a2015-01-09 16:15:22 -080011382 0, 0, 0, 21, 77, 53, 0, 47,
11383 23, 17, 0, 0, 15, 19, 19, 50,
11384 0, 0, 0, 0, 0, 1, 0, 0,
11385 0, 0, 0, 3, 13, 0, 0, 35,
11386 5, 11, 0, 38, 7, 7, 7, 41,
11387 44, 9, 62, 56, 25, 0, 0, 0,
11388 31, 29, 33, 59, 15, 0, 27, 0,
11389 0, 0, 0, 0, 0, 68, 0, 0,
11390 0, 71, 0, 0, 0, 65, 21, 77,
11391 53, 0, 47, 23, 17, 0, 0, 15,
11392 19, 19, 50, 0, 0, 74, 0
Chris Fallin91473dc2014-12-12 15:58:26 -080011393};
11394
11395static const int json_start = 1;
Chris Fallin91473dc2014-12-12 15:58:26 -080011396
11397static const int json_en_number_machine = 10;
11398static const int json_en_string_machine = 19;
11399static const int json_en_value_machine = 27;
11400static const int json_en_main = 1;
11401
11402
Josh Haberman78da6662016-01-13 19:05:43 -080011403#line 1249 "upb/json/parser.rl"
Chris Fallin91473dc2014-12-12 15:58:26 -080011404
11405size_t parse(void *closure, const void *hd, const char *buf, size_t size,
11406 const upb_bufhandle *handle) {
Chris Fallin91473dc2014-12-12 15:58:26 -080011407 upb_json_parser *parser = closure;
11408
Josh Habermane8ed0212015-06-08 17:56:03 -070011409 /* Variables used by Ragel's generated code. */
Chris Fallin91473dc2014-12-12 15:58:26 -080011410 int cs = parser->current_state;
11411 int *stack = parser->parser_stack;
11412 int top = parser->parser_top;
11413
11414 const char *p = buf;
11415 const char *pe = buf + size;
11416
Josh Habermane8ed0212015-06-08 17:56:03 -070011417 parser->handle = handle;
11418
11419 UPB_UNUSED(hd);
11420 UPB_UNUSED(handle);
11421
Chris Fallin97b663a2015-01-09 16:15:22 -080011422 capture_resume(parser, buf);
11423
Chris Fallin91473dc2014-12-12 15:58:26 -080011424
Josh Haberman78da6662016-01-13 19:05:43 -080011425#line 1329 "upb/json/parser.c"
Chris Fallin91473dc2014-12-12 15:58:26 -080011426 {
11427 int _klen;
11428 unsigned int _trans;
11429 const char *_acts;
11430 unsigned int _nacts;
11431 const char *_keys;
11432
11433 if ( p == pe )
11434 goto _test_eof;
11435 if ( cs == 0 )
11436 goto _out;
11437_resume:
11438 _keys = _json_trans_keys + _json_key_offsets[cs];
11439 _trans = _json_index_offsets[cs];
11440
11441 _klen = _json_single_lengths[cs];
11442 if ( _klen > 0 ) {
11443 const char *_lower = _keys;
11444 const char *_mid;
11445 const char *_upper = _keys + _klen - 1;
11446 while (1) {
11447 if ( _upper < _lower )
11448 break;
11449
11450 _mid = _lower + ((_upper-_lower) >> 1);
11451 if ( (*p) < *_mid )
11452 _upper = _mid - 1;
11453 else if ( (*p) > *_mid )
11454 _lower = _mid + 1;
11455 else {
11456 _trans += (unsigned int)(_mid - _keys);
11457 goto _match;
11458 }
11459 }
11460 _keys += _klen;
11461 _trans += _klen;
11462 }
11463
11464 _klen = _json_range_lengths[cs];
11465 if ( _klen > 0 ) {
11466 const char *_lower = _keys;
11467 const char *_mid;
11468 const char *_upper = _keys + (_klen<<1) - 2;
11469 while (1) {
11470 if ( _upper < _lower )
11471 break;
11472
11473 _mid = _lower + (((_upper-_lower) >> 1) & ~1);
11474 if ( (*p) < _mid[0] )
11475 _upper = _mid - 2;
11476 else if ( (*p) > _mid[1] )
11477 _lower = _mid + 2;
11478 else {
11479 _trans += (unsigned int)((_mid - _keys)>>1);
11480 goto _match;
11481 }
11482 }
11483 _trans += _klen;
11484 }
11485
11486_match:
11487 _trans = _json_indicies[_trans];
11488 cs = _json_trans_targs[_trans];
11489
11490 if ( _json_trans_actions[_trans] == 0 )
11491 goto _again;
11492
11493 _acts = _json_actions + _json_trans_actions[_trans];
11494 _nacts = (unsigned int) *_acts++;
11495 while ( _nacts-- > 0 )
11496 {
11497 switch ( *_acts++ )
11498 {
11499 case 0:
Josh Haberman78da6662016-01-13 19:05:43 -080011500#line 1161 "upb/json/parser.rl"
Chris Fallin91473dc2014-12-12 15:58:26 -080011501 { p--; {cs = stack[--top]; goto _again;} }
11502 break;
11503 case 1:
Josh Haberman78da6662016-01-13 19:05:43 -080011504#line 1162 "upb/json/parser.rl"
Chris Fallin91473dc2014-12-12 15:58:26 -080011505 { p--; {stack[top++] = cs; cs = 10; goto _again;} }
11506 break;
11507 case 2:
Josh Haberman78da6662016-01-13 19:05:43 -080011508#line 1166 "upb/json/parser.rl"
Chris Fallin91473dc2014-12-12 15:58:26 -080011509 { start_text(parser, p); }
11510 break;
11511 case 3:
Josh Haberman78da6662016-01-13 19:05:43 -080011512#line 1167 "upb/json/parser.rl"
Chris Fallin97b663a2015-01-09 16:15:22 -080011513 { CHECK_RETURN_TOP(end_text(parser, p)); }
Chris Fallin91473dc2014-12-12 15:58:26 -080011514 break;
11515 case 4:
Josh Haberman78da6662016-01-13 19:05:43 -080011516#line 1173 "upb/json/parser.rl"
Chris Fallin97b663a2015-01-09 16:15:22 -080011517 { start_hex(parser); }
Chris Fallin91473dc2014-12-12 15:58:26 -080011518 break;
11519 case 5:
Josh Haberman78da6662016-01-13 19:05:43 -080011520#line 1174 "upb/json/parser.rl"
Chris Fallin97b663a2015-01-09 16:15:22 -080011521 { hexdigit(parser, p); }
Chris Fallin91473dc2014-12-12 15:58:26 -080011522 break;
11523 case 6:
Josh Haberman78da6662016-01-13 19:05:43 -080011524#line 1175 "upb/json/parser.rl"
Chris Fallin97b663a2015-01-09 16:15:22 -080011525 { CHECK_RETURN_TOP(end_hex(parser)); }
Chris Fallin91473dc2014-12-12 15:58:26 -080011526 break;
11527 case 7:
Josh Haberman78da6662016-01-13 19:05:43 -080011528#line 1181 "upb/json/parser.rl"
Chris Fallin97b663a2015-01-09 16:15:22 -080011529 { CHECK_RETURN_TOP(escape(parser, p)); }
Chris Fallin91473dc2014-12-12 15:58:26 -080011530 break;
11531 case 8:
Josh Haberman78da6662016-01-13 19:05:43 -080011532#line 1187 "upb/json/parser.rl"
Chris Fallin91473dc2014-12-12 15:58:26 -080011533 { p--; {cs = stack[--top]; goto _again;} }
11534 break;
Chris Fallin97b663a2015-01-09 16:15:22 -080011535 case 9:
Josh Haberman78da6662016-01-13 19:05:43 -080011536#line 1190 "upb/json/parser.rl"
Chris Fallin97b663a2015-01-09 16:15:22 -080011537 { {stack[top++] = cs; cs = 19; goto _again;} }
11538 break;
11539 case 10:
Josh Haberman78da6662016-01-13 19:05:43 -080011540#line 1192 "upb/json/parser.rl"
Chris Fallin97b663a2015-01-09 16:15:22 -080011541 { p--; {stack[top++] = cs; cs = 27; goto _again;} }
11542 break;
11543 case 11:
Josh Haberman78da6662016-01-13 19:05:43 -080011544#line 1197 "upb/json/parser.rl"
Chris Fallin97b663a2015-01-09 16:15:22 -080011545 { start_member(parser); }
11546 break;
11547 case 12:
Josh Haberman78da6662016-01-13 19:05:43 -080011548#line 1198 "upb/json/parser.rl"
Chris Fallina5075922015-02-02 15:07:34 -080011549 { CHECK_RETURN_TOP(end_membername(parser)); }
Chris Fallin97b663a2015-01-09 16:15:22 -080011550 break;
11551 case 13:
Josh Haberman78da6662016-01-13 19:05:43 -080011552#line 1201 "upb/json/parser.rl"
Chris Fallina5075922015-02-02 15:07:34 -080011553 { end_member(parser); }
Chris Fallin97b663a2015-01-09 16:15:22 -080011554 break;
11555 case 14:
Josh Haberman78da6662016-01-13 19:05:43 -080011556#line 1207 "upb/json/parser.rl"
Chris Fallin97b663a2015-01-09 16:15:22 -080011557 { start_object(parser); }
11558 break;
11559 case 15:
Josh Haberman78da6662016-01-13 19:05:43 -080011560#line 1210 "upb/json/parser.rl"
Chris Fallin97b663a2015-01-09 16:15:22 -080011561 { end_object(parser); }
11562 break;
11563 case 16:
Josh Haberman78da6662016-01-13 19:05:43 -080011564#line 1216 "upb/json/parser.rl"
Chris Fallin97b663a2015-01-09 16:15:22 -080011565 { CHECK_RETURN_TOP(start_array(parser)); }
11566 break;
11567 case 17:
Josh Haberman78da6662016-01-13 19:05:43 -080011568#line 1220 "upb/json/parser.rl"
Chris Fallin97b663a2015-01-09 16:15:22 -080011569 { end_array(parser); }
11570 break;
11571 case 18:
Josh Haberman78da6662016-01-13 19:05:43 -080011572#line 1225 "upb/json/parser.rl"
Chris Fallin97b663a2015-01-09 16:15:22 -080011573 { start_number(parser, p); }
11574 break;
11575 case 19:
Josh Haberman78da6662016-01-13 19:05:43 -080011576#line 1226 "upb/json/parser.rl"
Chris Fallin97b663a2015-01-09 16:15:22 -080011577 { CHECK_RETURN_TOP(end_number(parser, p)); }
11578 break;
11579 case 20:
Josh Haberman78da6662016-01-13 19:05:43 -080011580#line 1228 "upb/json/parser.rl"
Chris Fallin97b663a2015-01-09 16:15:22 -080011581 { CHECK_RETURN_TOP(start_stringval(parser)); }
11582 break;
11583 case 21:
Josh Haberman78da6662016-01-13 19:05:43 -080011584#line 1229 "upb/json/parser.rl"
Chris Fallin97b663a2015-01-09 16:15:22 -080011585 { CHECK_RETURN_TOP(end_stringval(parser)); }
11586 break;
11587 case 22:
Josh Haberman78da6662016-01-13 19:05:43 -080011588#line 1231 "upb/json/parser.rl"
Chris Fallin97b663a2015-01-09 16:15:22 -080011589 { CHECK_RETURN_TOP(parser_putbool(parser, true)); }
11590 break;
11591 case 23:
Josh Haberman78da6662016-01-13 19:05:43 -080011592#line 1233 "upb/json/parser.rl"
Chris Fallin97b663a2015-01-09 16:15:22 -080011593 { CHECK_RETURN_TOP(parser_putbool(parser, false)); }
11594 break;
11595 case 24:
Josh Haberman78da6662016-01-13 19:05:43 -080011596#line 1235 "upb/json/parser.rl"
Chris Fallin97b663a2015-01-09 16:15:22 -080011597 { /* null value */ }
11598 break;
11599 case 25:
Josh Haberman78da6662016-01-13 19:05:43 -080011600#line 1237 "upb/json/parser.rl"
Chris Fallin97b663a2015-01-09 16:15:22 -080011601 { CHECK_RETURN_TOP(start_subobject(parser)); }
11602 break;
11603 case 26:
Josh Haberman78da6662016-01-13 19:05:43 -080011604#line 1238 "upb/json/parser.rl"
Chris Fallin97b663a2015-01-09 16:15:22 -080011605 { end_subobject(parser); }
11606 break;
11607 case 27:
Josh Haberman78da6662016-01-13 19:05:43 -080011608#line 1243 "upb/json/parser.rl"
Chris Fallin97b663a2015-01-09 16:15:22 -080011609 { p--; {cs = stack[--top]; goto _again;} }
11610 break;
Josh Haberman78da6662016-01-13 19:05:43 -080011611#line 1515 "upb/json/parser.c"
Chris Fallin91473dc2014-12-12 15:58:26 -080011612 }
11613 }
11614
11615_again:
11616 if ( cs == 0 )
11617 goto _out;
11618 if ( ++p != pe )
11619 goto _resume;
11620 _test_eof: {}
11621 _out: {}
11622 }
11623
Josh Haberman78da6662016-01-13 19:05:43 -080011624#line 1270 "upb/json/parser.rl"
Chris Fallin91473dc2014-12-12 15:58:26 -080011625
11626 if (p != pe) {
Josh Habermane67ef3d2016-04-14 20:27:45 -070011627 upb_status_seterrf(&parser->status, "Parse error at '%.*s'\n", pe - p, p);
Josh Haberman181c7f22015-07-15 11:05:10 -070011628 upb_env_reporterror(parser->env, &parser->status);
Chris Fallin97b663a2015-01-09 16:15:22 -080011629 } else {
11630 capture_suspend(parser, &p);
Chris Fallin91473dc2014-12-12 15:58:26 -080011631 }
11632
11633error:
Josh Habermane8ed0212015-06-08 17:56:03 -070011634 /* Save parsing state back to parser. */
Chris Fallin91473dc2014-12-12 15:58:26 -080011635 parser->current_state = cs;
11636 parser->parser_top = top;
11637
11638 return p - buf;
11639}
11640
11641bool end(void *closure, const void *hd) {
11642 UPB_UNUSED(closure);
11643 UPB_UNUSED(hd);
Chris Fallind3262772015-05-14 18:24:26 -070011644
Josh Habermane8ed0212015-06-08 17:56:03 -070011645 /* Prevent compile warning on unused static constants. */
Chris Fallind3262772015-05-14 18:24:26 -070011646 UPB_UNUSED(json_start);
11647 UPB_UNUSED(json_en_number_machine);
11648 UPB_UNUSED(json_en_string_machine);
11649 UPB_UNUSED(json_en_value_machine);
11650 UPB_UNUSED(json_en_main);
Chris Fallin91473dc2014-12-12 15:58:26 -080011651 return true;
11652}
11653
Chris Fallind3262772015-05-14 18:24:26 -070011654static void json_parser_reset(upb_json_parser *p) {
Josh Habermane8ed0212015-06-08 17:56:03 -070011655 int cs;
11656 int top;
11657
Chris Fallin91473dc2014-12-12 15:58:26 -080011658 p->top = p->stack;
11659 p->top->f = NULL;
Chris Fallina5075922015-02-02 15:07:34 -080011660 p->top->is_map = false;
11661 p->top->is_mapentry = false;
Chris Fallin91473dc2014-12-12 15:58:26 -080011662
Josh Habermane8ed0212015-06-08 17:56:03 -070011663 /* Emit Ragel initialization of the parser. */
Chris Fallin91473dc2014-12-12 15:58:26 -080011664
Josh Haberman78da6662016-01-13 19:05:43 -080011665#line 1569 "upb/json/parser.c"
Chris Fallin91473dc2014-12-12 15:58:26 -080011666 {
11667 cs = json_start;
11668 top = 0;
11669 }
11670
Josh Haberman78da6662016-01-13 19:05:43 -080011671#line 1310 "upb/json/parser.rl"
Chris Fallin91473dc2014-12-12 15:58:26 -080011672 p->current_state = cs;
11673 p->parser_top = top;
Chris Fallin97b663a2015-01-09 16:15:22 -080011674 accumulate_clear(p);
11675 p->multipart_state = MULTIPART_INACTIVE;
11676 p->capture = NULL;
Chris Fallind3262772015-05-14 18:24:26 -070011677 p->accumulated = NULL;
Josh Haberman181c7f22015-07-15 11:05:10 -070011678 upb_status_clear(&p->status);
Chris Fallin91473dc2014-12-12 15:58:26 -080011679}
11680
Josh Haberman78da6662016-01-13 19:05:43 -080011681static void visit_json_parsermethod(const upb_refcounted *r,
11682 upb_refcounted_visit *visit,
11683 void *closure) {
11684 const upb_json_parsermethod *method = (upb_json_parsermethod*)r;
11685 visit(r, upb_msgdef_upcast2(method->msg), closure);
11686}
11687
11688static void free_json_parsermethod(upb_refcounted *r) {
11689 upb_json_parsermethod *method = (upb_json_parsermethod*)r;
11690
11691 upb_inttable_iter i;
11692 upb_inttable_begin(&i, &method->name_tables);
11693 for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
11694 upb_value val = upb_inttable_iter_value(&i);
11695 upb_strtable *t = upb_value_getptr(val);
11696 upb_strtable_uninit(t);
11697 free(t);
11698 }
11699
11700 upb_inttable_uninit(&method->name_tables);
11701
11702 free(r);
11703}
11704
11705static void add_jsonname_table(upb_json_parsermethod *m, const upb_msgdef* md) {
11706 upb_msg_field_iter i;
11707 upb_strtable *t;
11708
Josh Habermanf654d492016-02-18 11:07:51 -080011709 /* It would be nice to stack-allocate this, but protobufs do not limit the
11710 * length of fields to any reasonable limit. */
11711 char *buf = NULL;
11712 size_t len = 0;
11713
Josh Haberman78da6662016-01-13 19:05:43 -080011714 if (upb_inttable_lookupptr(&m->name_tables, md, NULL)) {
11715 return;
11716 }
11717
11718 /* TODO(haberman): handle malloc failure. */
11719 t = malloc(sizeof(*t));
11720 upb_strtable_init(t, UPB_CTYPE_CONSTPTR);
11721 upb_inttable_insertptr(&m->name_tables, md, upb_value_ptr(t));
11722
11723 for(upb_msg_field_begin(&i, md);
11724 !upb_msg_field_done(&i);
11725 upb_msg_field_next(&i)) {
11726 const upb_fielddef *f = upb_msg_iter_field(&i);
Josh Haberman94e54b32016-04-14 12:06:09 -070011727
Josh Haberman194ad622016-04-14 18:33:17 -070011728 /* Add an entry for the JSON name. */
Josh Habermanf654d492016-02-18 11:07:51 -080011729 size_t field_len = upb_fielddef_getjsonname(f, buf, len);
11730 if (field_len > len) {
Josh Haberman94e54b32016-04-14 12:06:09 -070011731 size_t len2;
Josh Habermanf654d492016-02-18 11:07:51 -080011732 buf = realloc(buf, field_len);
11733 len = field_len;
Josh Haberman94e54b32016-04-14 12:06:09 -070011734 len2 = upb_fielddef_getjsonname(f, buf, len);
11735 UPB_ASSERT_VAR(len2, len == len2);
Josh Habermanf654d492016-02-18 11:07:51 -080011736 }
Josh Haberman78da6662016-01-13 19:05:43 -080011737 upb_strtable_insert(t, buf, upb_value_constptr(f));
Josh Haberman78da6662016-01-13 19:05:43 -080011738
Josh Haberman194ad622016-04-14 18:33:17 -070011739 if (strcmp(buf, upb_fielddef_name(f)) != 0) {
11740 /* Since the JSON name is different from the regular field name, add an
11741 * entry for the raw name (compliant proto3 JSON parsers must accept
11742 * both). */
Josh Haberman94e54b32016-04-14 12:06:09 -070011743 upb_strtable_insert(t, upb_fielddef_name(f), upb_value_constptr(f));
11744 }
11745
Josh Haberman78da6662016-01-13 19:05:43 -080011746 if (upb_fielddef_issubmsg(f)) {
11747 add_jsonname_table(m, upb_fielddef_msgsubdef(f));
11748 }
11749 }
Josh Habermanf654d492016-02-18 11:07:51 -080011750
11751 free(buf);
Josh Haberman78da6662016-01-13 19:05:43 -080011752}
Chris Fallind3262772015-05-14 18:24:26 -070011753
11754/* Public API *****************************************************************/
11755
Josh Haberman78da6662016-01-13 19:05:43 -080011756upb_json_parser *upb_json_parser_create(upb_env *env,
11757 const upb_json_parsermethod *method,
11758 upb_sink *output) {
Chris Fallind3262772015-05-14 18:24:26 -070011759#ifndef NDEBUG
11760 const size_t size_before = upb_env_bytesallocated(env);
11761#endif
11762 upb_json_parser *p = upb_env_malloc(env, sizeof(upb_json_parser));
11763 if (!p) return false;
11764
11765 p->env = env;
Josh Haberman78da6662016-01-13 19:05:43 -080011766 p->method = method;
Chris Fallind3262772015-05-14 18:24:26 -070011767 p->limit = p->stack + UPB_JSON_MAX_DEPTH;
11768 p->accumulate_buf = NULL;
11769 p->accumulate_buf_size = 0;
Josh Haberman78da6662016-01-13 19:05:43 -080011770 upb_bytessink_reset(&p->input_, &method->input_handler_, p);
Chris Fallind3262772015-05-14 18:24:26 -070011771
11772 json_parser_reset(p);
11773 upb_sink_reset(&p->top->sink, output->handlers, output->closure);
11774 p->top->m = upb_handlers_msgdef(output->handlers);
Josh Haberman78da6662016-01-13 19:05:43 -080011775 set_name_table(p, p->top);
Chris Fallind3262772015-05-14 18:24:26 -070011776
Josh Haberman181c7f22015-07-15 11:05:10 -070011777 /* If this fails, uncomment and increase the value in parser.h. */
11778 /* fprintf(stderr, "%zd\n", upb_env_bytesallocated(env) - size_before); */
Chris Fallind3262772015-05-14 18:24:26 -070011779 assert(upb_env_bytesallocated(env) - size_before <= UPB_JSON_PARSER_SIZE);
11780 return p;
Chris Fallin91473dc2014-12-12 15:58:26 -080011781}
11782
11783upb_bytessink *upb_json_parser_input(upb_json_parser *p) {
11784 return &p->input_;
11785}
Josh Haberman78da6662016-01-13 19:05:43 -080011786
11787upb_json_parsermethod *upb_json_parsermethod_new(const upb_msgdef* md,
11788 const void* owner) {
11789 static const struct upb_refcounted_vtbl vtbl = {visit_json_parsermethod,
11790 free_json_parsermethod};
11791 upb_json_parsermethod *ret = malloc(sizeof(*ret));
11792 upb_refcounted_init(upb_json_parsermethod_upcast_mutable(ret), &vtbl, owner);
11793
11794 ret->msg = md;
11795 upb_ref2(md, ret);
11796
11797 upb_byteshandler_init(&ret->input_handler_);
11798 upb_byteshandler_setstring(&ret->input_handler_, parse, ret);
11799 upb_byteshandler_setendstr(&ret->input_handler_, end, ret);
11800
11801 upb_inttable_init(&ret->name_tables, UPB_CTYPE_PTR);
11802
11803 add_jsonname_table(ret, md);
11804
11805 return ret;
11806}
11807
11808const upb_byteshandler *upb_json_parsermethod_inputhandler(
11809 const upb_json_parsermethod *m) {
11810 return &m->input_handler_;
11811}
Chris Fallin91473dc2014-12-12 15:58:26 -080011812/*
Josh Haberman181c7f22015-07-15 11:05:10 -070011813** This currently uses snprintf() to format primitives, and could be optimized
11814** further.
11815*/
Chris Fallin91473dc2014-12-12 15:58:26 -080011816
11817
11818#include <stdlib.h>
11819#include <stdio.h>
11820#include <string.h>
11821#include <stdint.h>
11822
Chris Fallind3262772015-05-14 18:24:26 -070011823struct upb_json_printer {
11824 upb_sink input_;
Josh Habermane8ed0212015-06-08 17:56:03 -070011825 /* BytesSink closure. */
Chris Fallind3262772015-05-14 18:24:26 -070011826 void *subc_;
11827 upb_bytessink *output_;
11828
Josh Habermane8ed0212015-06-08 17:56:03 -070011829 /* We track the depth so that we know when to emit startstr/endstr on the
11830 * output. */
Chris Fallind3262772015-05-14 18:24:26 -070011831 int depth_;
11832
Josh Habermane8ed0212015-06-08 17:56:03 -070011833 /* Have we emitted the first element? This state is necessary to emit commas
11834 * without leaving a trailing comma in arrays/maps. We keep this state per
11835 * frame depth.
11836 *
11837 * Why max_depth * 2? UPB_MAX_HANDLER_DEPTH counts depth as nested messages.
11838 * We count frames (contexts in which we separate elements by commas) as both
11839 * repeated fields and messages (maps), and the worst case is a
11840 * message->repeated field->submessage->repeated field->... nesting. */
Chris Fallind3262772015-05-14 18:24:26 -070011841 bool first_elem_[UPB_MAX_HANDLER_DEPTH * 2];
11842};
11843
Josh Habermane8ed0212015-06-08 17:56:03 -070011844/* StringPiece; a pointer plus a length. */
Chris Fallin91473dc2014-12-12 15:58:26 -080011845typedef struct {
Josh Haberman78da6662016-01-13 19:05:43 -080011846 char *ptr;
Chris Fallin91473dc2014-12-12 15:58:26 -080011847 size_t len;
11848} strpc;
11849
Josh Haberman78da6662016-01-13 19:05:43 -080011850void freestrpc(void *ptr) {
11851 strpc *pc = ptr;
11852 free(pc->ptr);
11853 free(pc);
11854}
11855
11856/* Convert fielddef name to JSON name and return as a string piece. */
Josh Haberman194ad622016-04-14 18:33:17 -070011857strpc *newstrpc(upb_handlers *h, const upb_fielddef *f,
11858 bool preserve_fieldnames) {
Josh Haberman78da6662016-01-13 19:05:43 -080011859 /* TODO(haberman): handle malloc failure. */
Chris Fallin91473dc2014-12-12 15:58:26 -080011860 strpc *ret = malloc(sizeof(*ret));
Josh Haberman194ad622016-04-14 18:33:17 -070011861 if (preserve_fieldnames) {
Josh Haberman94e54b32016-04-14 12:06:09 -070011862 ret->ptr = upb_strdup(upb_fielddef_name(f));
11863 ret->len = strlen(ret->ptr);
11864 } else {
11865 size_t len;
11866 ret->len = upb_fielddef_getjsonname(f, NULL, 0);
11867 ret->ptr = malloc(ret->len);
11868 len = upb_fielddef_getjsonname(f, ret->ptr, ret->len);
11869 UPB_ASSERT_VAR(len, len == ret->len);
11870 ret->len--; /* NULL */
11871 }
Josh Haberman78da6662016-01-13 19:05:43 -080011872
11873 upb_handlers_addcleanup(h, ret, freestrpc);
Chris Fallin91473dc2014-12-12 15:58:26 -080011874 return ret;
11875}
11876
Josh Habermane8ed0212015-06-08 17:56:03 -070011877/* ------------ JSON string printing: values, maps, arrays ------------------ */
Chris Fallin91473dc2014-12-12 15:58:26 -080011878
11879static void print_data(
11880 upb_json_printer *p, const char *buf, unsigned int len) {
Josh Habermane8ed0212015-06-08 17:56:03 -070011881 /* TODO: Will need to change if we support pushback from the sink. */
Chris Fallin91473dc2014-12-12 15:58:26 -080011882 size_t n = upb_bytessink_putbuf(p->output_, p->subc_, buf, len, NULL);
11883 UPB_ASSERT_VAR(n, n == len);
11884}
11885
11886static void print_comma(upb_json_printer *p) {
11887 if (!p->first_elem_[p->depth_]) {
11888 print_data(p, ",", 1);
11889 }
11890 p->first_elem_[p->depth_] = false;
11891}
11892
Josh Habermane8ed0212015-06-08 17:56:03 -070011893/* Helpers that print properly formatted elements to the JSON output stream. */
Chris Fallin91473dc2014-12-12 15:58:26 -080011894
Josh Habermane8ed0212015-06-08 17:56:03 -070011895/* Used for escaping control chars in strings. */
Chris Fallin91473dc2014-12-12 15:58:26 -080011896static const char kControlCharLimit = 0x20;
11897
Josh Habermane8ed0212015-06-08 17:56:03 -070011898UPB_INLINE bool is_json_escaped(char c) {
11899 /* See RFC 4627. */
Chris Fallin91473dc2014-12-12 15:58:26 -080011900 unsigned char uc = (unsigned char)c;
11901 return uc < kControlCharLimit || uc == '"' || uc == '\\';
11902}
11903
Josh Habermanf654d492016-02-18 11:07:51 -080011904UPB_INLINE const char* json_nice_escape(char c) {
Chris Fallin91473dc2014-12-12 15:58:26 -080011905 switch (c) {
11906 case '"': return "\\\"";
11907 case '\\': return "\\\\";
11908 case '\b': return "\\b";
11909 case '\f': return "\\f";
11910 case '\n': return "\\n";
11911 case '\r': return "\\r";
11912 case '\t': return "\\t";
11913 default: return NULL;
11914 }
11915}
11916
Josh Habermane8ed0212015-06-08 17:56:03 -070011917/* Write a properly escaped string chunk. The surrounding quotes are *not*
11918 * printed; this is so that the caller has the option of emitting the string
11919 * content in chunks. */
Chris Fallin91473dc2014-12-12 15:58:26 -080011920static void putstring(upb_json_printer *p, const char *buf, unsigned int len) {
11921 const char* unescaped_run = NULL;
Josh Habermane8ed0212015-06-08 17:56:03 -070011922 unsigned int i;
11923 for (i = 0; i < len; i++) {
Chris Fallin91473dc2014-12-12 15:58:26 -080011924 char c = buf[i];
Josh Habermane8ed0212015-06-08 17:56:03 -070011925 /* Handle escaping. */
Chris Fallin91473dc2014-12-12 15:58:26 -080011926 if (is_json_escaped(c)) {
Josh Habermane8ed0212015-06-08 17:56:03 -070011927 /* Use a "nice" escape, like \n, if one exists for this character. */
Chris Fallin91473dc2014-12-12 15:58:26 -080011928 const char* escape = json_nice_escape(c);
Josh Habermane8ed0212015-06-08 17:56:03 -070011929 /* If we don't have a specific 'nice' escape code, use a \uXXXX-style
11930 * escape. */
Chris Fallin91473dc2014-12-12 15:58:26 -080011931 char escape_buf[8];
11932 if (!escape) {
11933 unsigned char byte = (unsigned char)c;
Josh Habermane8ed0212015-06-08 17:56:03 -070011934 _upb_snprintf(escape_buf, sizeof(escape_buf), "\\u%04x", (int)byte);
Chris Fallin91473dc2014-12-12 15:58:26 -080011935 escape = escape_buf;
11936 }
11937
Josh Habermane8ed0212015-06-08 17:56:03 -070011938 /* N.B. that we assume that the input encoding is equal to the output
11939 * encoding (both UTF-8 for now), so for chars >= 0x20 and != \, ", we
11940 * can simply pass the bytes through. */
Chris Fallin91473dc2014-12-12 15:58:26 -080011941
Josh Habermane8ed0212015-06-08 17:56:03 -070011942 /* If there's a current run of unescaped chars, print that run first. */
Chris Fallin91473dc2014-12-12 15:58:26 -080011943 if (unescaped_run) {
11944 print_data(p, unescaped_run, &buf[i] - unescaped_run);
11945 unescaped_run = NULL;
11946 }
Josh Habermane8ed0212015-06-08 17:56:03 -070011947 /* Then print the escape code. */
Chris Fallin91473dc2014-12-12 15:58:26 -080011948 print_data(p, escape, strlen(escape));
11949 } else {
Josh Habermane8ed0212015-06-08 17:56:03 -070011950 /* Add to the current unescaped run of characters. */
Chris Fallin91473dc2014-12-12 15:58:26 -080011951 if (unescaped_run == NULL) {
11952 unescaped_run = &buf[i];
11953 }
11954 }
11955 }
11956
Josh Habermane8ed0212015-06-08 17:56:03 -070011957 /* If the string ended in a run of unescaped characters, print that last run. */
Chris Fallin91473dc2014-12-12 15:58:26 -080011958 if (unescaped_run) {
11959 print_data(p, unescaped_run, &buf[len] - unescaped_run);
11960 }
11961}
11962
11963#define CHKLENGTH(x) if (!(x)) return -1;
11964
Josh Habermane8ed0212015-06-08 17:56:03 -070011965/* Helpers that format floating point values according to our custom formats.
11966 * Right now we use %.8g and %.17g for float/double, respectively, to match
11967 * proto2::util::JsonFormat's defaults. May want to change this later. */
Chris Fallin91473dc2014-12-12 15:58:26 -080011968
11969static size_t fmt_double(double val, char* buf, size_t length) {
Josh Habermane8ed0212015-06-08 17:56:03 -070011970 size_t n = _upb_snprintf(buf, length, "%.17g", val);
Chris Fallin91473dc2014-12-12 15:58:26 -080011971 CHKLENGTH(n > 0 && n < length);
11972 return n;
11973}
11974
11975static size_t fmt_float(float val, char* buf, size_t length) {
Josh Habermane8ed0212015-06-08 17:56:03 -070011976 size_t n = _upb_snprintf(buf, length, "%.8g", val);
Chris Fallin91473dc2014-12-12 15:58:26 -080011977 CHKLENGTH(n > 0 && n < length);
11978 return n;
11979}
11980
11981static size_t fmt_bool(bool val, char* buf, size_t length) {
Josh Habermane8ed0212015-06-08 17:56:03 -070011982 size_t n = _upb_snprintf(buf, length, "%s", (val ? "true" : "false"));
Chris Fallin91473dc2014-12-12 15:58:26 -080011983 CHKLENGTH(n > 0 && n < length);
11984 return n;
11985}
11986
11987static size_t fmt_int64(long val, char* buf, size_t length) {
Josh Habermane8ed0212015-06-08 17:56:03 -070011988 size_t n = _upb_snprintf(buf, length, "%ld", val);
Chris Fallin91473dc2014-12-12 15:58:26 -080011989 CHKLENGTH(n > 0 && n < length);
11990 return n;
11991}
11992
11993static size_t fmt_uint64(unsigned long long val, char* buf, size_t length) {
Josh Habermane8ed0212015-06-08 17:56:03 -070011994 size_t n = _upb_snprintf(buf, length, "%llu", val);
Chris Fallin91473dc2014-12-12 15:58:26 -080011995 CHKLENGTH(n > 0 && n < length);
11996 return n;
11997}
11998
Josh Habermane8ed0212015-06-08 17:56:03 -070011999/* Print a map key given a field name. Called by scalar field handlers and by
12000 * startseq for repeated fields. */
Chris Fallin91473dc2014-12-12 15:58:26 -080012001static bool putkey(void *closure, const void *handler_data) {
12002 upb_json_printer *p = closure;
12003 const strpc *key = handler_data;
12004 print_comma(p);
12005 print_data(p, "\"", 1);
12006 putstring(p, key->ptr, key->len);
12007 print_data(p, "\":", 2);
12008 return true;
12009}
12010
Chris Fallind3262772015-05-14 18:24:26 -070012011#define CHKFMT(val) if ((val) == (size_t)-1) return false;
Chris Fallin91473dc2014-12-12 15:58:26 -080012012#define CHK(val) if (!(val)) return false;
12013
12014#define TYPE_HANDLERS(type, fmt_func) \
12015 static bool put##type(void *closure, const void *handler_data, type val) { \
12016 upb_json_printer *p = closure; \
Chris Fallin91473dc2014-12-12 15:58:26 -080012017 char data[64]; \
12018 size_t length = fmt_func(val, data, sizeof(data)); \
Josh Habermane8ed0212015-06-08 17:56:03 -070012019 UPB_UNUSED(handler_data); \
Chris Fallin91473dc2014-12-12 15:58:26 -080012020 CHKFMT(length); \
12021 print_data(p, data, length); \
12022 return true; \
12023 } \
12024 static bool scalar_##type(void *closure, const void *handler_data, \
12025 type val) { \
12026 CHK(putkey(closure, handler_data)); \
12027 CHK(put##type(closure, handler_data, val)); \
12028 return true; \
12029 } \
12030 static bool repeated_##type(void *closure, const void *handler_data, \
Chris Fallina5075922015-02-02 15:07:34 -080012031 type val) { \
Chris Fallin91473dc2014-12-12 15:58:26 -080012032 upb_json_printer *p = closure; \
12033 print_comma(p); \
12034 CHK(put##type(closure, handler_data, val)); \
12035 return true; \
12036 }
12037
Chris Fallina5075922015-02-02 15:07:34 -080012038#define TYPE_HANDLERS_MAPKEY(type, fmt_func) \
12039 static bool putmapkey_##type(void *closure, const void *handler_data, \
12040 type val) { \
12041 upb_json_printer *p = closure; \
12042 print_data(p, "\"", 1); \
12043 CHK(put##type(closure, handler_data, val)); \
12044 print_data(p, "\":", 2); \
12045 return true; \
12046 }
12047
Josh Habermane8ed0212015-06-08 17:56:03 -070012048TYPE_HANDLERS(double, fmt_double)
12049TYPE_HANDLERS(float, fmt_float)
12050TYPE_HANDLERS(bool, fmt_bool)
12051TYPE_HANDLERS(int32_t, fmt_int64)
12052TYPE_HANDLERS(uint32_t, fmt_int64)
12053TYPE_HANDLERS(int64_t, fmt_int64)
12054TYPE_HANDLERS(uint64_t, fmt_uint64)
Chris Fallin91473dc2014-12-12 15:58:26 -080012055
Josh Habermane8ed0212015-06-08 17:56:03 -070012056/* double and float are not allowed to be map keys. */
12057TYPE_HANDLERS_MAPKEY(bool, fmt_bool)
12058TYPE_HANDLERS_MAPKEY(int32_t, fmt_int64)
12059TYPE_HANDLERS_MAPKEY(uint32_t, fmt_int64)
12060TYPE_HANDLERS_MAPKEY(int64_t, fmt_int64)
12061TYPE_HANDLERS_MAPKEY(uint64_t, fmt_uint64)
Chris Fallina5075922015-02-02 15:07:34 -080012062
Chris Fallin91473dc2014-12-12 15:58:26 -080012063#undef TYPE_HANDLERS
Chris Fallina5075922015-02-02 15:07:34 -080012064#undef TYPE_HANDLERS_MAPKEY
Chris Fallin91473dc2014-12-12 15:58:26 -080012065
12066typedef struct {
12067 void *keyname;
12068 const upb_enumdef *enumdef;
12069} EnumHandlerData;
12070
12071static bool scalar_enum(void *closure, const void *handler_data,
12072 int32_t val) {
12073 const EnumHandlerData *hd = handler_data;
12074 upb_json_printer *p = closure;
Josh Habermane8ed0212015-06-08 17:56:03 -070012075 const char *symbolic_name;
12076
Chris Fallin91473dc2014-12-12 15:58:26 -080012077 CHK(putkey(closure, hd->keyname));
12078
Josh Habermane8ed0212015-06-08 17:56:03 -070012079 symbolic_name = upb_enumdef_iton(hd->enumdef, val);
Chris Fallin91473dc2014-12-12 15:58:26 -080012080 if (symbolic_name) {
12081 print_data(p, "\"", 1);
12082 putstring(p, symbolic_name, strlen(symbolic_name));
12083 print_data(p, "\"", 1);
12084 } else {
12085 putint32_t(closure, NULL, val);
12086 }
12087
12088 return true;
12089}
12090
Chris Fallina5075922015-02-02 15:07:34 -080012091static void print_enum_symbolic_name(upb_json_printer *p,
12092 const upb_enumdef *def,
12093 int32_t val) {
12094 const char *symbolic_name = upb_enumdef_iton(def, val);
12095 if (symbolic_name) {
12096 print_data(p, "\"", 1);
12097 putstring(p, symbolic_name, strlen(symbolic_name));
12098 print_data(p, "\"", 1);
12099 } else {
12100 putint32_t(p, NULL, val);
12101 }
12102}
12103
Chris Fallin91473dc2014-12-12 15:58:26 -080012104static bool repeated_enum(void *closure, const void *handler_data,
12105 int32_t val) {
12106 const EnumHandlerData *hd = handler_data;
12107 upb_json_printer *p = closure;
12108 print_comma(p);
12109
Chris Fallina5075922015-02-02 15:07:34 -080012110 print_enum_symbolic_name(p, hd->enumdef, val);
12111
12112 return true;
12113}
12114
12115static bool mapvalue_enum(void *closure, const void *handler_data,
12116 int32_t val) {
12117 const EnumHandlerData *hd = handler_data;
12118 upb_json_printer *p = closure;
12119
12120 print_enum_symbolic_name(p, hd->enumdef, val);
Chris Fallin91473dc2014-12-12 15:58:26 -080012121
12122 return true;
12123}
12124
12125static void *scalar_startsubmsg(void *closure, const void *handler_data) {
12126 return putkey(closure, handler_data) ? closure : UPB_BREAK;
12127}
12128
12129static void *repeated_startsubmsg(void *closure, const void *handler_data) {
Chris Fallin91473dc2014-12-12 15:58:26 -080012130 upb_json_printer *p = closure;
Josh Habermane8ed0212015-06-08 17:56:03 -070012131 UPB_UNUSED(handler_data);
Chris Fallin91473dc2014-12-12 15:58:26 -080012132 print_comma(p);
12133 return closure;
12134}
12135
Chris Fallina5075922015-02-02 15:07:34 -080012136static void start_frame(upb_json_printer *p) {
12137 p->depth_++;
Chris Fallin91473dc2014-12-12 15:58:26 -080012138 p->first_elem_[p->depth_] = true;
12139 print_data(p, "{", 1);
Chris Fallina5075922015-02-02 15:07:34 -080012140}
12141
12142static void end_frame(upb_json_printer *p) {
12143 print_data(p, "}", 1);
12144 p->depth_--;
12145}
12146
12147static bool printer_startmsg(void *closure, const void *handler_data) {
Chris Fallina5075922015-02-02 15:07:34 -080012148 upb_json_printer *p = closure;
Josh Habermane8ed0212015-06-08 17:56:03 -070012149 UPB_UNUSED(handler_data);
Chris Fallina5075922015-02-02 15:07:34 -080012150 if (p->depth_ == 0) {
12151 upb_bytessink_start(p->output_, 0, &p->subc_);
12152 }
12153 start_frame(p);
Chris Fallin91473dc2014-12-12 15:58:26 -080012154 return true;
12155}
12156
Chris Fallina5075922015-02-02 15:07:34 -080012157static bool printer_endmsg(void *closure, const void *handler_data, upb_status *s) {
Josh Habermane8ed0212015-06-08 17:56:03 -070012158 upb_json_printer *p = closure;
Chris Fallin91473dc2014-12-12 15:58:26 -080012159 UPB_UNUSED(handler_data);
12160 UPB_UNUSED(s);
Chris Fallina5075922015-02-02 15:07:34 -080012161 end_frame(p);
12162 if (p->depth_ == 0) {
Chris Fallin91473dc2014-12-12 15:58:26 -080012163 upb_bytessink_end(p->output_);
12164 }
Chris Fallin91473dc2014-12-12 15:58:26 -080012165 return true;
12166}
12167
12168static void *startseq(void *closure, const void *handler_data) {
12169 upb_json_printer *p = closure;
12170 CHK(putkey(closure, handler_data));
12171 p->depth_++;
12172 p->first_elem_[p->depth_] = true;
12173 print_data(p, "[", 1);
12174 return closure;
12175}
12176
12177static bool endseq(void *closure, const void *handler_data) {
Chris Fallin91473dc2014-12-12 15:58:26 -080012178 upb_json_printer *p = closure;
Josh Habermane8ed0212015-06-08 17:56:03 -070012179 UPB_UNUSED(handler_data);
Chris Fallin91473dc2014-12-12 15:58:26 -080012180 print_data(p, "]", 1);
12181 p->depth_--;
12182 return true;
12183}
12184
Chris Fallina5075922015-02-02 15:07:34 -080012185static void *startmap(void *closure, const void *handler_data) {
12186 upb_json_printer *p = closure;
12187 CHK(putkey(closure, handler_data));
12188 p->depth_++;
12189 p->first_elem_[p->depth_] = true;
12190 print_data(p, "{", 1);
12191 return closure;
12192}
12193
12194static bool endmap(void *closure, const void *handler_data) {
Chris Fallina5075922015-02-02 15:07:34 -080012195 upb_json_printer *p = closure;
Josh Habermane8ed0212015-06-08 17:56:03 -070012196 UPB_UNUSED(handler_data);
Chris Fallina5075922015-02-02 15:07:34 -080012197 print_data(p, "}", 1);
12198 p->depth_--;
12199 return true;
12200}
12201
Chris Fallin91473dc2014-12-12 15:58:26 -080012202static size_t putstr(void *closure, const void *handler_data, const char *str,
12203 size_t len, const upb_bufhandle *handle) {
Josh Habermane8ed0212015-06-08 17:56:03 -070012204 upb_json_printer *p = closure;
Chris Fallin91473dc2014-12-12 15:58:26 -080012205 UPB_UNUSED(handler_data);
12206 UPB_UNUSED(handle);
Chris Fallin91473dc2014-12-12 15:58:26 -080012207 putstring(p, str, len);
12208 return len;
12209}
12210
Josh Habermane8ed0212015-06-08 17:56:03 -070012211/* This has to Base64 encode the bytes, because JSON has no "bytes" type. */
Chris Fallin91473dc2014-12-12 15:58:26 -080012212static size_t putbytes(void *closure, const void *handler_data, const char *str,
12213 size_t len, const upb_bufhandle *handle) {
Chris Fallin91473dc2014-12-12 15:58:26 -080012214 upb_json_printer *p = closure;
12215
Josh Habermane8ed0212015-06-08 17:56:03 -070012216 /* This is the regular base64, not the "web-safe" version. */
Chris Fallin91473dc2014-12-12 15:58:26 -080012217 static const char base64[] =
12218 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
12219
Josh Habermane8ed0212015-06-08 17:56:03 -070012220 /* Base64-encode. */
Chris Fallin91473dc2014-12-12 15:58:26 -080012221 char data[16000];
12222 const char *limit = data + sizeof(data);
12223 const unsigned char *from = (const unsigned char*)str;
12224 char *to = data;
12225 size_t remaining = len;
Josh Habermane8ed0212015-06-08 17:56:03 -070012226 size_t bytes;
12227
12228 UPB_UNUSED(handler_data);
12229 UPB_UNUSED(handle);
12230
Chris Fallin91473dc2014-12-12 15:58:26 -080012231 while (remaining > 2) {
Josh Habermane8ed0212015-06-08 17:56:03 -070012232 /* TODO(haberman): handle encoded lengths > sizeof(data) */
Chris Fallin91473dc2014-12-12 15:58:26 -080012233 UPB_ASSERT_VAR(limit, (limit - to) >= 4);
12234
12235 to[0] = base64[from[0] >> 2];
12236 to[1] = base64[((from[0] & 0x3) << 4) | (from[1] >> 4)];
12237 to[2] = base64[((from[1] & 0xf) << 2) | (from[2] >> 6)];
12238 to[3] = base64[from[2] & 0x3f];
12239
12240 remaining -= 3;
12241 to += 4;
12242 from += 3;
12243 }
12244
12245 switch (remaining) {
12246 case 2:
12247 to[0] = base64[from[0] >> 2];
12248 to[1] = base64[((from[0] & 0x3) << 4) | (from[1] >> 4)];
12249 to[2] = base64[(from[1] & 0xf) << 2];
12250 to[3] = '=';
12251 to += 4;
12252 from += 2;
12253 break;
12254 case 1:
12255 to[0] = base64[from[0] >> 2];
12256 to[1] = base64[((from[0] & 0x3) << 4)];
12257 to[2] = '=';
12258 to[3] = '=';
12259 to += 4;
12260 from += 1;
12261 break;
12262 }
12263
Josh Habermane8ed0212015-06-08 17:56:03 -070012264 bytes = to - data;
Chris Fallin91473dc2014-12-12 15:58:26 -080012265 print_data(p, "\"", 1);
12266 putstring(p, data, bytes);
12267 print_data(p, "\"", 1);
12268 return len;
12269}
12270
12271static void *scalar_startstr(void *closure, const void *handler_data,
12272 size_t size_hint) {
Josh Habermane8ed0212015-06-08 17:56:03 -070012273 upb_json_printer *p = closure;
Chris Fallin91473dc2014-12-12 15:58:26 -080012274 UPB_UNUSED(handler_data);
12275 UPB_UNUSED(size_hint);
Chris Fallin91473dc2014-12-12 15:58:26 -080012276 CHK(putkey(closure, handler_data));
12277 print_data(p, "\"", 1);
12278 return p;
12279}
12280
12281static size_t scalar_str(void *closure, const void *handler_data,
12282 const char *str, size_t len,
12283 const upb_bufhandle *handle) {
12284 CHK(putstr(closure, handler_data, str, len, handle));
12285 return len;
12286}
12287
12288static bool scalar_endstr(void *closure, const void *handler_data) {
Chris Fallin91473dc2014-12-12 15:58:26 -080012289 upb_json_printer *p = closure;
Josh Habermane8ed0212015-06-08 17:56:03 -070012290 UPB_UNUSED(handler_data);
Chris Fallin91473dc2014-12-12 15:58:26 -080012291 print_data(p, "\"", 1);
12292 return true;
12293}
12294
12295static void *repeated_startstr(void *closure, const void *handler_data,
12296 size_t size_hint) {
Josh Habermane8ed0212015-06-08 17:56:03 -070012297 upb_json_printer *p = closure;
Chris Fallin91473dc2014-12-12 15:58:26 -080012298 UPB_UNUSED(handler_data);
12299 UPB_UNUSED(size_hint);
Chris Fallin91473dc2014-12-12 15:58:26 -080012300 print_comma(p);
12301 print_data(p, "\"", 1);
12302 return p;
12303}
12304
12305static size_t repeated_str(void *closure, const void *handler_data,
12306 const char *str, size_t len,
12307 const upb_bufhandle *handle) {
12308 CHK(putstr(closure, handler_data, str, len, handle));
12309 return len;
12310}
12311
12312static bool repeated_endstr(void *closure, const void *handler_data) {
Chris Fallin91473dc2014-12-12 15:58:26 -080012313 upb_json_printer *p = closure;
Josh Habermane8ed0212015-06-08 17:56:03 -070012314 UPB_UNUSED(handler_data);
Chris Fallin91473dc2014-12-12 15:58:26 -080012315 print_data(p, "\"", 1);
12316 return true;
12317}
12318
Chris Fallina5075922015-02-02 15:07:34 -080012319static void *mapkeyval_startstr(void *closure, const void *handler_data,
12320 size_t size_hint) {
Josh Habermane8ed0212015-06-08 17:56:03 -070012321 upb_json_printer *p = closure;
Chris Fallina5075922015-02-02 15:07:34 -080012322 UPB_UNUSED(handler_data);
12323 UPB_UNUSED(size_hint);
Chris Fallina5075922015-02-02 15:07:34 -080012324 print_data(p, "\"", 1);
12325 return p;
12326}
12327
12328static size_t mapkey_str(void *closure, const void *handler_data,
12329 const char *str, size_t len,
12330 const upb_bufhandle *handle) {
12331 CHK(putstr(closure, handler_data, str, len, handle));
12332 return len;
12333}
12334
12335static bool mapkey_endstr(void *closure, const void *handler_data) {
Chris Fallina5075922015-02-02 15:07:34 -080012336 upb_json_printer *p = closure;
Josh Habermane8ed0212015-06-08 17:56:03 -070012337 UPB_UNUSED(handler_data);
Chris Fallina5075922015-02-02 15:07:34 -080012338 print_data(p, "\":", 2);
12339 return true;
12340}
12341
12342static bool mapvalue_endstr(void *closure, const void *handler_data) {
Chris Fallina5075922015-02-02 15:07:34 -080012343 upb_json_printer *p = closure;
Josh Habermane8ed0212015-06-08 17:56:03 -070012344 UPB_UNUSED(handler_data);
Chris Fallina5075922015-02-02 15:07:34 -080012345 print_data(p, "\"", 1);
12346 return true;
12347}
12348
Chris Fallin91473dc2014-12-12 15:58:26 -080012349static size_t scalar_bytes(void *closure, const void *handler_data,
12350 const char *str, size_t len,
12351 const upb_bufhandle *handle) {
12352 CHK(putkey(closure, handler_data));
12353 CHK(putbytes(closure, handler_data, str, len, handle));
12354 return len;
12355}
12356
12357static size_t repeated_bytes(void *closure, const void *handler_data,
12358 const char *str, size_t len,
12359 const upb_bufhandle *handle) {
12360 upb_json_printer *p = closure;
12361 print_comma(p);
12362 CHK(putbytes(closure, handler_data, str, len, handle));
12363 return len;
12364}
12365
Chris Fallina5075922015-02-02 15:07:34 -080012366static size_t mapkey_bytes(void *closure, const void *handler_data,
12367 const char *str, size_t len,
12368 const upb_bufhandle *handle) {
12369 upb_json_printer *p = closure;
12370 CHK(putbytes(closure, handler_data, str, len, handle));
12371 print_data(p, ":", 1);
12372 return len;
12373}
12374
12375static void set_enum_hd(upb_handlers *h,
12376 const upb_fielddef *f,
Josh Haberman194ad622016-04-14 18:33:17 -070012377 bool preserve_fieldnames,
Chris Fallina5075922015-02-02 15:07:34 -080012378 upb_handlerattr *attr) {
12379 EnumHandlerData *hd = malloc(sizeof(EnumHandlerData));
12380 hd->enumdef = (const upb_enumdef *)upb_fielddef_subdef(f);
Josh Haberman194ad622016-04-14 18:33:17 -070012381 hd->keyname = newstrpc(h, f, preserve_fieldnames);
Chris Fallina5075922015-02-02 15:07:34 -080012382 upb_handlers_addcleanup(h, hd, free);
12383 upb_handlerattr_sethandlerdata(attr, hd);
12384}
12385
Josh Habermane8ed0212015-06-08 17:56:03 -070012386/* Set up handlers for a mapentry submessage (i.e., an individual key/value pair
12387 * in a map).
12388 *
12389 * TODO: Handle missing key, missing value, out-of-order key/value, or repeated
12390 * key or value cases properly. The right way to do this is to allocate a
12391 * temporary structure at the start of a mapentry submessage, store key and
12392 * value data in it as key and value handlers are called, and then print the
12393 * key/value pair once at the end of the submessage. If we don't do this, we
12394 * should at least detect the case and throw an error. However, so far all of
12395 * our sources that emit mapentry messages do so canonically (with one key
12396 * field, and then one value field), so this is not a pressing concern at the
12397 * moment. */
Josh Haberman194ad622016-04-14 18:33:17 -070012398void printer_sethandlers_mapentry(const void *closure, bool preserve_fieldnames,
12399 upb_handlers *h) {
Chris Fallina5075922015-02-02 15:07:34 -080012400 const upb_msgdef *md = upb_handlers_msgdef(h);
12401
Josh Habermane8ed0212015-06-08 17:56:03 -070012402 /* A mapentry message is printed simply as '"key": value'. Rather than
12403 * special-case key and value for every type below, we just handle both
12404 * fields explicitly here. */
Chris Fallina5075922015-02-02 15:07:34 -080012405 const upb_fielddef* key_field = upb_msgdef_itof(md, UPB_MAPENTRY_KEY);
12406 const upb_fielddef* value_field = upb_msgdef_itof(md, UPB_MAPENTRY_VALUE);
Chris Fallin91473dc2014-12-12 15:58:26 -080012407
12408 upb_handlerattr empty_attr = UPB_HANDLERATTR_INITIALIZER;
Chris Fallin91473dc2014-12-12 15:58:26 -080012409
Josh Habermane8ed0212015-06-08 17:56:03 -070012410 UPB_UNUSED(closure);
12411
Chris Fallina5075922015-02-02 15:07:34 -080012412 switch (upb_fielddef_type(key_field)) {
12413 case UPB_TYPE_INT32:
12414 upb_handlers_setint32(h, key_field, putmapkey_int32_t, &empty_attr);
12415 break;
12416 case UPB_TYPE_INT64:
12417 upb_handlers_setint64(h, key_field, putmapkey_int64_t, &empty_attr);
12418 break;
12419 case UPB_TYPE_UINT32:
12420 upb_handlers_setuint32(h, key_field, putmapkey_uint32_t, &empty_attr);
12421 break;
12422 case UPB_TYPE_UINT64:
12423 upb_handlers_setuint64(h, key_field, putmapkey_uint64_t, &empty_attr);
12424 break;
12425 case UPB_TYPE_BOOL:
12426 upb_handlers_setbool(h, key_field, putmapkey_bool, &empty_attr);
12427 break;
12428 case UPB_TYPE_STRING:
12429 upb_handlers_setstartstr(h, key_field, mapkeyval_startstr, &empty_attr);
12430 upb_handlers_setstring(h, key_field, mapkey_str, &empty_attr);
12431 upb_handlers_setendstr(h, key_field, mapkey_endstr, &empty_attr);
12432 break;
12433 case UPB_TYPE_BYTES:
12434 upb_handlers_setstring(h, key_field, mapkey_bytes, &empty_attr);
12435 break;
12436 default:
12437 assert(false);
12438 break;
12439 }
12440
12441 switch (upb_fielddef_type(value_field)) {
12442 case UPB_TYPE_INT32:
12443 upb_handlers_setint32(h, value_field, putint32_t, &empty_attr);
12444 break;
12445 case UPB_TYPE_INT64:
12446 upb_handlers_setint64(h, value_field, putint64_t, &empty_attr);
12447 break;
12448 case UPB_TYPE_UINT32:
12449 upb_handlers_setuint32(h, value_field, putuint32_t, &empty_attr);
12450 break;
12451 case UPB_TYPE_UINT64:
12452 upb_handlers_setuint64(h, value_field, putuint64_t, &empty_attr);
12453 break;
12454 case UPB_TYPE_BOOL:
12455 upb_handlers_setbool(h, value_field, putbool, &empty_attr);
12456 break;
12457 case UPB_TYPE_FLOAT:
12458 upb_handlers_setfloat(h, value_field, putfloat, &empty_attr);
12459 break;
12460 case UPB_TYPE_DOUBLE:
12461 upb_handlers_setdouble(h, value_field, putdouble, &empty_attr);
12462 break;
12463 case UPB_TYPE_STRING:
12464 upb_handlers_setstartstr(h, value_field, mapkeyval_startstr, &empty_attr);
12465 upb_handlers_setstring(h, value_field, putstr, &empty_attr);
12466 upb_handlers_setendstr(h, value_field, mapvalue_endstr, &empty_attr);
12467 break;
12468 case UPB_TYPE_BYTES:
12469 upb_handlers_setstring(h, value_field, putbytes, &empty_attr);
12470 break;
12471 case UPB_TYPE_ENUM: {
12472 upb_handlerattr enum_attr = UPB_HANDLERATTR_INITIALIZER;
Josh Haberman194ad622016-04-14 18:33:17 -070012473 set_enum_hd(h, value_field, preserve_fieldnames, &enum_attr);
Chris Fallina5075922015-02-02 15:07:34 -080012474 upb_handlers_setint32(h, value_field, mapvalue_enum, &enum_attr);
12475 upb_handlerattr_uninit(&enum_attr);
12476 break;
12477 }
12478 case UPB_TYPE_MESSAGE:
Josh Habermane8ed0212015-06-08 17:56:03 -070012479 /* No handler necessary -- the submsg handlers will print the message
12480 * as appropriate. */
Chris Fallina5075922015-02-02 15:07:34 -080012481 break;
12482 }
12483
12484 upb_handlerattr_uninit(&empty_attr);
12485}
12486
12487void printer_sethandlers(const void *closure, upb_handlers *h) {
Chris Fallina5075922015-02-02 15:07:34 -080012488 const upb_msgdef *md = upb_handlers_msgdef(h);
12489 bool is_mapentry = upb_msgdef_mapentry(md);
12490 upb_handlerattr empty_attr = UPB_HANDLERATTR_INITIALIZER;
Josh Habermane8ed0212015-06-08 17:56:03 -070012491 upb_msg_field_iter i;
Josh Haberman194ad622016-04-14 18:33:17 -070012492 const bool *preserve_fieldnames_ptr = closure;
12493 const bool preserve_fieldnames = *preserve_fieldnames_ptr;
Chris Fallina5075922015-02-02 15:07:34 -080012494
12495 if (is_mapentry) {
Josh Habermane8ed0212015-06-08 17:56:03 -070012496 /* mapentry messages are sufficiently different that we handle them
12497 * separately. */
Josh Haberman194ad622016-04-14 18:33:17 -070012498 printer_sethandlers_mapentry(closure, preserve_fieldnames, h);
Chris Fallina5075922015-02-02 15:07:34 -080012499 return;
12500 }
12501
12502 upb_handlers_setstartmsg(h, printer_startmsg, &empty_attr);
12503 upb_handlers_setendmsg(h, printer_endmsg, &empty_attr);
12504
12505#define TYPE(type, name, ctype) \
12506 case type: \
12507 if (upb_fielddef_isseq(f)) { \
12508 upb_handlers_set##name(h, f, repeated_##ctype, &empty_attr); \
12509 } else { \
12510 upb_handlers_set##name(h, f, scalar_##ctype, &name_attr); \
12511 } \
Chris Fallin91473dc2014-12-12 15:58:26 -080012512 break;
12513
Chris Fallina5075922015-02-02 15:07:34 -080012514 upb_msg_field_begin(&i, md);
Chris Fallinfcd88892015-01-13 18:14:39 -080012515 for(; !upb_msg_field_done(&i); upb_msg_field_next(&i)) {
Chris Fallin91473dc2014-12-12 15:58:26 -080012516 const upb_fielddef *f = upb_msg_iter_field(&i);
12517
12518 upb_handlerattr name_attr = UPB_HANDLERATTR_INITIALIZER;
Josh Haberman194ad622016-04-14 18:33:17 -070012519 upb_handlerattr_sethandlerdata(&name_attr,
12520 newstrpc(h, f, preserve_fieldnames));
Chris Fallin91473dc2014-12-12 15:58:26 -080012521
Chris Fallina5075922015-02-02 15:07:34 -080012522 if (upb_fielddef_ismap(f)) {
12523 upb_handlers_setstartseq(h, f, startmap, &name_attr);
12524 upb_handlers_setendseq(h, f, endmap, &name_attr);
12525 } else if (upb_fielddef_isseq(f)) {
Chris Fallin91473dc2014-12-12 15:58:26 -080012526 upb_handlers_setstartseq(h, f, startseq, &name_attr);
12527 upb_handlers_setendseq(h, f, endseq, &empty_attr);
12528 }
12529
12530 switch (upb_fielddef_type(f)) {
12531 TYPE(UPB_TYPE_FLOAT, float, float);
12532 TYPE(UPB_TYPE_DOUBLE, double, double);
12533 TYPE(UPB_TYPE_BOOL, bool, bool);
12534 TYPE(UPB_TYPE_INT32, int32, int32_t);
12535 TYPE(UPB_TYPE_UINT32, uint32, uint32_t);
12536 TYPE(UPB_TYPE_INT64, int64, int64_t);
12537 TYPE(UPB_TYPE_UINT64, uint64, uint64_t);
12538 case UPB_TYPE_ENUM: {
Josh Habermane8ed0212015-06-08 17:56:03 -070012539 /* For now, we always emit symbolic names for enums. We may want an
12540 * option later to control this behavior, but we will wait for a real
12541 * need first. */
Chris Fallin91473dc2014-12-12 15:58:26 -080012542 upb_handlerattr enum_attr = UPB_HANDLERATTR_INITIALIZER;
Josh Haberman194ad622016-04-14 18:33:17 -070012543 set_enum_hd(h, f, preserve_fieldnames, &enum_attr);
Chris Fallin91473dc2014-12-12 15:58:26 -080012544
12545 if (upb_fielddef_isseq(f)) {
12546 upb_handlers_setint32(h, f, repeated_enum, &enum_attr);
12547 } else {
12548 upb_handlers_setint32(h, f, scalar_enum, &enum_attr);
12549 }
12550
12551 upb_handlerattr_uninit(&enum_attr);
12552 break;
12553 }
12554 case UPB_TYPE_STRING:
12555 if (upb_fielddef_isseq(f)) {
12556 upb_handlers_setstartstr(h, f, repeated_startstr, &empty_attr);
12557 upb_handlers_setstring(h, f, repeated_str, &empty_attr);
12558 upb_handlers_setendstr(h, f, repeated_endstr, &empty_attr);
12559 } else {
12560 upb_handlers_setstartstr(h, f, scalar_startstr, &name_attr);
12561 upb_handlers_setstring(h, f, scalar_str, &empty_attr);
12562 upb_handlers_setendstr(h, f, scalar_endstr, &empty_attr);
12563 }
12564 break;
12565 case UPB_TYPE_BYTES:
Josh Habermane8ed0212015-06-08 17:56:03 -070012566 /* XXX: this doesn't support strings that span buffers yet. The base64
12567 * encoder will need to be made resumable for this to work properly. */
Chris Fallin91473dc2014-12-12 15:58:26 -080012568 if (upb_fielddef_isseq(f)) {
12569 upb_handlers_setstring(h, f, repeated_bytes, &empty_attr);
12570 } else {
12571 upb_handlers_setstring(h, f, scalar_bytes, &name_attr);
12572 }
12573 break;
12574 case UPB_TYPE_MESSAGE:
12575 if (upb_fielddef_isseq(f)) {
12576 upb_handlers_setstartsubmsg(h, f, repeated_startsubmsg, &name_attr);
12577 } else {
12578 upb_handlers_setstartsubmsg(h, f, scalar_startsubmsg, &name_attr);
12579 }
12580 break;
12581 }
12582
12583 upb_handlerattr_uninit(&name_attr);
12584 }
12585
12586 upb_handlerattr_uninit(&empty_attr);
12587#undef TYPE
12588}
12589
Chris Fallind3262772015-05-14 18:24:26 -070012590static void json_printer_reset(upb_json_printer *p) {
12591 p->depth_ = 0;
12592}
12593
12594
Chris Fallin91473dc2014-12-12 15:58:26 -080012595/* Public API *****************************************************************/
12596
Chris Fallind3262772015-05-14 18:24:26 -070012597upb_json_printer *upb_json_printer_create(upb_env *e, const upb_handlers *h,
12598 upb_bytessink *output) {
12599#ifndef NDEBUG
12600 size_t size_before = upb_env_bytesallocated(e);
12601#endif
Chris Fallin91473dc2014-12-12 15:58:26 -080012602
Chris Fallind3262772015-05-14 18:24:26 -070012603 upb_json_printer *p = upb_env_malloc(e, sizeof(upb_json_printer));
12604 if (!p) return NULL;
Chris Fallin91473dc2014-12-12 15:58:26 -080012605
Chris Fallin91473dc2014-12-12 15:58:26 -080012606 p->output_ = output;
Chris Fallind3262772015-05-14 18:24:26 -070012607 json_printer_reset(p);
12608 upb_sink_reset(&p->input_, h, p);
12609
Josh Habermane8ed0212015-06-08 17:56:03 -070012610 /* If this fails, increase the value in printer.h. */
Chris Fallind3262772015-05-14 18:24:26 -070012611 assert(upb_env_bytesallocated(e) - size_before <= UPB_JSON_PRINTER_SIZE);
12612 return p;
Chris Fallin91473dc2014-12-12 15:58:26 -080012613}
12614
12615upb_sink *upb_json_printer_input(upb_json_printer *p) {
12616 return &p->input_;
12617}
12618
12619const upb_handlers *upb_json_printer_newhandlers(const upb_msgdef *md,
Josh Haberman194ad622016-04-14 18:33:17 -070012620 bool preserve_fieldnames,
Chris Fallin91473dc2014-12-12 15:58:26 -080012621 const void *owner) {
Josh Haberman194ad622016-04-14 18:33:17 -070012622 return upb_handlers_newfrozen(
12623 md, owner, printer_sethandlers, &preserve_fieldnames);
Chris Fallin91473dc2014-12-12 15:58:26 -080012624}