1b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer// Amalgamated source file
2b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include "upb.h"
3b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <ctype.h>
6b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <stdlib.h>
7b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <string.h>
8b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammertypedef struct {
10b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  size_t len;
11b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  char str[1];  /* Null-terminated string data follows. */
12b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer} str_t;
13b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
14b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic str_t *newstr(const char *data, size_t len) {
15b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  str_t *ret = upb_gmalloc(sizeof(*ret) + len);
16b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!ret) return NULL;
17b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  ret->len = len;
18b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  memcpy(ret->str, data, len);
19b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  ret->str[len] = '\0';
20b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return ret;
21b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
22b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
23b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void freestr(str_t *s) { upb_gfree(s); }
24b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
25b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* isalpha() etc. from <ctype.h> are locale-dependent, which we don't want. */
26b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool upb_isbetween(char c, char low, char high) {
27b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return c >= low && c <= high;
28b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
29b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
30b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool upb_isletter(char c) {
31b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_isbetween(c, 'A', 'Z') || upb_isbetween(c, 'a', 'z') || c == '_';
32b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
33b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
34b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool upb_isalphanum(char c) {
35b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_isletter(c) || upb_isbetween(c, '0', '9');
36b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
37b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
38b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool upb_isident(const char *str, size_t len, bool full, upb_status *s) {
39b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bool start = true;
40b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  size_t i;
41b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for (i = 0; i < len; i++) {
42b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    char c = str[i];
43b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (c == '.') {
44b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (start || !full) {
45b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_status_seterrf(s, "invalid name: unexpected '.' (%s)", str);
46b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        return false;
47b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
48b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      start = true;
49b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    } else if (start) {
50b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (!upb_isletter(c)) {
51b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_status_seterrf(
52b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer            s, "invalid name: path components must start with a letter (%s)",
53b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer            str);
54b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        return false;
55b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
56b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      start = false;
57b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    } else {
58b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (!upb_isalphanum(c)) {
59b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_status_seterrf(s, "invalid name: non-alphanumeric character (%s)",
60b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                           str);
61b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        return false;
62b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
63b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
64b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
65b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return !start;
66b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
67b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
68b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool upb_isoneof(const upb_refcounted *def) {
69b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return def->vtbl == &upb_oneofdef_vtbl;
70b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
71b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
72b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool upb_isfield(const upb_refcounted *def) {
73b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return def->vtbl == &upb_fielddef_vtbl;
74b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
75b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
76b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic const upb_oneofdef *upb_trygetoneof(const upb_refcounted *def) {
77b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_isoneof(def) ? (const upb_oneofdef*)def : NULL;
78b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
79b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
80b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic const upb_fielddef *upb_trygetfield(const upb_refcounted *def) {
81b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_isfield(def) ? (const upb_fielddef*)def : NULL;
82b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
83b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
84b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
85b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* upb_def ********************************************************************/
86b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
87b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerupb_deftype_t upb_def_type(const upb_def *d) { return d->type; }
88b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
89b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst char *upb_def_fullname(const upb_def *d) { return d->fullname; }
90b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
91b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst char *upb_def_name(const upb_def *d) {
92b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const char *p;
93b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
94b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (d->fullname == NULL) {
95b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return NULL;
96b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else if ((p = strrchr(d->fullname, '.')) == NULL) {
97b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* No '.' in the name, return the full string. */
98b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return d->fullname;
99b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
100b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Return one past the last '.'. */
101b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return p + 1;
102b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
103b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
104b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
105b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_def_setfullname(upb_def *def, const char *fullname, upb_status *s) {
106b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(!upb_def_isfrozen(def));
107b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!upb_isident(fullname, strlen(fullname), true, s)) {
108b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
109b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
110b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
111b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  fullname = upb_gstrdup(fullname);
112b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!fullname) {
113b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_upberr_setoom(s);
114b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
115b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
116b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
117b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_gfree((void*)def->fullname);
118b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  def->fullname = fullname;
119b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
120b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
121b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
122b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_filedef *upb_def_file(const upb_def *d) { return d->file; }
123b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
124b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerupb_def *upb_def_dup(const upb_def *def, const void *o) {
125b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  switch (def->type) {
126b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_DEF_MSG:
127b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return upb_msgdef_upcast_mutable(
128b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          upb_msgdef_dup(upb_downcast_msgdef(def), o));
129b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_DEF_FIELD:
130b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return upb_fielddef_upcast_mutable(
131b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          upb_fielddef_dup(upb_downcast_fielddef(def), o));
132b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_DEF_ENUM:
133b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return upb_enumdef_upcast_mutable(
134b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          upb_enumdef_dup(upb_downcast_enumdef(def), o));
135b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    default: assert(false); return NULL;
136b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
137b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
138b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
139b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool upb_def_init(upb_def *def, upb_deftype_t type,
140b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                         const struct upb_refcounted_vtbl *vtbl,
141b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                         const void *owner) {
142b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!upb_refcounted_init(upb_def_upcast_mutable(def), vtbl, owner)) return false;
143b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  def->type = type;
144b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  def->fullname = NULL;
145b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  def->came_from_user = false;
146b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  def->file = NULL;
147b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
148b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
149b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
150b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void upb_def_uninit(upb_def *def) {
151b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_gfree((void*)def->fullname);
152b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
153b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
154b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic const char *msgdef_name(const upb_msgdef *m) {
155b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const char *name = upb_def_fullname(upb_msgdef_upcast(m));
156b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return name ? name : "(anonymous)";
157b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
158b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
159b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool upb_validate_field(upb_fielddef *f, upb_status *s) {
160b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upb_fielddef_name(f) == NULL || upb_fielddef_number(f) == 0) {
161b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_status_seterrmsg(s, "fielddef must have name and number set");
162b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
163b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
164b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
165b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!f->type_is_set_) {
166b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_status_seterrmsg(s, "fielddef type was not initialized");
167b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
168b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
169b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
170b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upb_fielddef_lazy(f) &&
171b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_fielddef_descriptortype(f) != UPB_DESCRIPTOR_TYPE_MESSAGE) {
172b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_status_seterrmsg(s,
173b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                         "only length-delimited submessage fields may be lazy");
174b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
175b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
176b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
177b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upb_fielddef_hassubdef(f)) {
178b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    const upb_def *subdef;
179b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
180b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (f->subdef_is_symbolic) {
181b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_status_seterrf(s, "field '%s.%s' has not been resolved",
182b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                         msgdef_name(f->msg.def), upb_fielddef_name(f));
183b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return false;
184b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
185b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
186b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    subdef = upb_fielddef_subdef(f);
187b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (subdef == NULL) {
188b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_status_seterrf(s, "field %s.%s is missing required subdef",
189b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                         msgdef_name(f->msg.def), upb_fielddef_name(f));
190b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return false;
191b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
192b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
193b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (!upb_def_isfrozen(subdef) && !subdef->came_from_user) {
194b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_status_seterrf(s,
195b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                         "subdef of field %s.%s is not frozen or being frozen",
196b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                         msgdef_name(f->msg.def), upb_fielddef_name(f));
197b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return false;
198b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
199b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
200b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
201b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upb_fielddef_type(f) == UPB_TYPE_ENUM) {
202b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    bool has_default_name = upb_fielddef_enumhasdefaultstr(f);
203b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    bool has_default_number = upb_fielddef_enumhasdefaultint32(f);
204b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
205b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Previously verified by upb_validate_enumdef(). */
206b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    assert(upb_enumdef_numvals(upb_fielddef_enumsubdef(f)) > 0);
207b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
208b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* We've already validated that we have an associated enumdef and that it
209b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * has at least one member, so at least one of these should be true.
210b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * Because if the user didn't set anything, we'll pick up the enum's
211b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * default, but if the user *did* set something we should at least pick up
212b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * the one they set (int32 or string). */
213b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    assert(has_default_name || has_default_number);
214b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
215b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (!has_default_name) {
216b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_status_seterrf(s,
217b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                         "enum default for field %s.%s (%d) is not in the enum",
218b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                         msgdef_name(f->msg.def), upb_fielddef_name(f),
219b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                         upb_fielddef_defaultint32(f));
220b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return false;
221b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
222b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
223b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (!has_default_number) {
224b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_status_seterrf(s,
225b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                         "enum default for field %s.%s (%s) is not in the enum",
226b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                         msgdef_name(f->msg.def), upb_fielddef_name(f),
227b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                         upb_fielddef_defaultstr(f, NULL));
228b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return false;
229b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
230b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
231b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Lift the effective numeric default into the field's default slot, in case
232b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * we were only getting it "by reference" from the enumdef. */
233b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_fielddef_setdefaultint32(f, upb_fielddef_defaultint32(f));
234b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
235b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
236b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Ensure that MapEntry submessages only appear as repeated fields, not
237b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * optional/required (singular) fields. */
238b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upb_fielddef_type(f) == UPB_TYPE_MESSAGE &&
239b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_fielddef_msgsubdef(f) != NULL) {
240b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    const upb_msgdef *subdef = upb_fielddef_msgsubdef(f);
241b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (upb_msgdef_mapentry(subdef) && !upb_fielddef_isseq(f)) {
242b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_status_seterrf(s,
243b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                         "Field %s refers to mapentry message but is not "
244b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                         "a repeated field",
245b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                         upb_fielddef_name(f) ? upb_fielddef_name(f) :
246b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                         "(unnamed)");
247b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return false;
248b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
249b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
250b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
251b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
252b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
253b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
254b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool upb_validate_enumdef(const upb_enumdef *e, upb_status *s) {
255b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upb_enumdef_numvals(e) == 0) {
256b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_status_seterrf(s, "enum %s has no members (must have at least one)",
257b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                       upb_enumdef_fullname(e));
258b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
259b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
260b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
261b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
262b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
263b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
264b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* All submessage fields are lower than all other fields.
265b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Secondly, fields are increasing in order. */
266b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammeruint32_t field_rank(const upb_fielddef *f) {
267b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  uint32_t ret = upb_fielddef_number(f);
268b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const uint32_t high_bit = 1 << 30;
269b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(ret < high_bit);
270b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!upb_fielddef_issubmsg(f))
271b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    ret |= high_bit;
272b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return ret;
273b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
274b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
275b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerint cmp_fields(const void *p1, const void *p2) {
276b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const upb_fielddef *f1 = *(upb_fielddef*const*)p1;
277b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const upb_fielddef *f2 = *(upb_fielddef*const*)p2;
278b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return field_rank(f1) - field_rank(f2);
279b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
280b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
281b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool assign_msg_indices(upb_msgdef *m, upb_status *s) {
282b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Sort fields.  upb internally relies on UPB_TYPE_MESSAGE fields having the
283b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * lowest indexes, but we do not publicly guarantee this. */
284b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_msg_field_iter j;
285b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  int i;
286b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  uint32_t selector;
287b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  int n = upb_msgdef_numfields(m);
288b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_fielddef **fields;
289b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
290b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (n == 0) {
291b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    m->selector_count = UPB_STATIC_SELECTOR_COUNT;
292b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    m->submsg_field_count = 0;
293b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return true;
294b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
295b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
296b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  fields = upb_gmalloc(n * sizeof(*fields));
297b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!fields) {
298b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_upberr_setoom(s);
299b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
300b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
301b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
302b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  m->submsg_field_count = 0;
303b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for(i = 0, upb_msg_field_begin(&j, m);
304b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      !upb_msg_field_done(&j);
305b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_msg_field_next(&j), i++) {
306b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_fielddef *f = upb_msg_iter_field(&j);
307b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    assert(f->msg.def == m);
308b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (!upb_validate_field(f, s)) {
309b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_gfree(fields);
310b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return false;
311b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
312b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (upb_fielddef_issubmsg(f)) {
313b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      m->submsg_field_count++;
314b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
315b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    fields[i] = f;
316b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
317b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
318b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  qsort(fields, n, sizeof(*fields), cmp_fields);
319b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
320b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  selector = UPB_STATIC_SELECTOR_COUNT + m->submsg_field_count;
321b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for (i = 0; i < n; i++) {
322b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_fielddef *f = fields[i];
323b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    f->index_ = i;
324b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    f->selector_base = selector + upb_handlers_selectorbaseoffset(f);
325b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    selector += upb_handlers_selectorcount(f);
326b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
327b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  m->selector_count = selector;
328b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
329b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#ifndef NDEBUG
330b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {
331b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Verify that all selectors for the message are distinct. */
332b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#define TRY(type) \
333b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (upb_handlers_getselector(f, type, &sel)) upb_inttable_insert(&t, sel, v);
334b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
335b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_inttable t;
336b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_value v;
337b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_selector_t sel;
338b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
339b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_inttable_init(&t, UPB_CTYPE_BOOL);
340b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    v = upb_value_bool(true);
341b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_inttable_insert(&t, UPB_STARTMSG_SELECTOR, v);
342b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_inttable_insert(&t, UPB_ENDMSG_SELECTOR, v);
343b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    for(upb_msg_field_begin(&j, m);
344b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        !upb_msg_field_done(&j);
345b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_msg_field_next(&j)) {
346b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_fielddef *f = upb_msg_iter_field(&j);
347b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      /* These calls will assert-fail in upb_table if the value already
348b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer       * exists. */
349b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      TRY(UPB_HANDLER_INT32);
350b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      TRY(UPB_HANDLER_INT64)
351b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      TRY(UPB_HANDLER_UINT32)
352b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      TRY(UPB_HANDLER_UINT64)
353b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      TRY(UPB_HANDLER_FLOAT)
354b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      TRY(UPB_HANDLER_DOUBLE)
355b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      TRY(UPB_HANDLER_BOOL)
356b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      TRY(UPB_HANDLER_STARTSTR)
357b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      TRY(UPB_HANDLER_STRING)
358b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      TRY(UPB_HANDLER_ENDSTR)
359b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      TRY(UPB_HANDLER_STARTSUBMSG)
360b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      TRY(UPB_HANDLER_ENDSUBMSG)
361b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      TRY(UPB_HANDLER_STARTSEQ)
362b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      TRY(UPB_HANDLER_ENDSEQ)
363b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
364b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_inttable_uninit(&t);
365b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
366b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#undef TRY
367b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#endif
368b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
369b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_gfree(fields);
370b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
371b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
372b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
373b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool _upb_def_validate(upb_def *const*defs, size_t n, upb_status *s) {
374b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  size_t i;
375b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
376b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* First perform validation, in two passes so we can check that we have a
377b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * transitive closure without needing to search. */
378b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for (i = 0; i < n; i++) {
379b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_def *def = defs[i];
380b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (upb_def_isfrozen(def)) {
381b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      /* Could relax this requirement if it's annoying. */
382b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_status_seterrmsg(s, "def is already frozen");
383b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      goto err;
384b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    } else if (def->type == UPB_DEF_FIELD) {
385b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_status_seterrmsg(s, "standalone fielddefs can not be frozen");
386b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      goto err;
387b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    } else if (def->type == UPB_DEF_ENUM) {
388b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (!upb_validate_enumdef(upb_dyncast_enumdef(def), s)) {
389b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        goto err;
390b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
391b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    } else {
392b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      /* Set now to detect transitive closure in the second pass. */
393b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      def->came_from_user = true;
394b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
395b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
396b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
397b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Second pass of validation.  Also assign selector bases and indexes, and
398b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * compact tables. */
399b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for (i = 0; i < n; i++) {
400b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_def *def = defs[i];
401b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_msgdef *m = upb_dyncast_msgdef_mutable(def);
402b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_enumdef *e = upb_dyncast_enumdef_mutable(def);
403b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (m) {
404b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_inttable_compact(&m->itof);
405b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (!assign_msg_indices(m, s)) {
406b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        goto err;
407b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
408b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    } else if (e) {
409b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_inttable_compact(&e->iton);
410b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
411b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
412b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
413b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
414b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
415b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammererr:
416b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for (i = 0; i < n; i++) {
417b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_def *def = defs[i];
418b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    def->came_from_user = false;
419b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
420b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(!(s && upb_ok(s)));
421b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return false;
422b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
423b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
424b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_def_freeze(upb_def *const* defs, size_t n, upb_status *s) {
425b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Def graph contains FieldDefs between each MessageDef, so double the
426b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * limit. */
427b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const size_t maxdepth = UPB_MAX_MESSAGE_DEPTH * 2;
428b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
429b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!_upb_def_validate(defs, n, s)) {
430b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
431b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
432b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
433b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
434b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Validation all passed; freeze the objects. */
435b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_refcounted_freeze((upb_refcounted *const*)defs, n, s, maxdepth);
436b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
437b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
438b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
439b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* upb_enumdef ****************************************************************/
440b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
441b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void upb_enumdef_free(upb_refcounted *r) {
442b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_enumdef *e = (upb_enumdef*)r;
443b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_iter i;
444b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_begin(&i, &e->iton);
445b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for( ; !upb_inttable_done(&i); upb_inttable_next(&i)) {
446b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* To clean up the upb_gstrdup() from upb_enumdef_addval(). */
447b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_gfree(upb_value_getcstr(upb_inttable_iter_value(&i)));
448b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
449b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_strtable_uninit(&e->ntoi);
450b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_uninit(&e->iton);
451b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_def_uninit(upb_enumdef_upcast_mutable(e));
452b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_gfree(e);
453b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
454b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
455b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst struct upb_refcounted_vtbl upb_enumdef_vtbl = {NULL, &upb_enumdef_free};
456b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
457b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerupb_enumdef *upb_enumdef_new(const void *owner) {
458b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_enumdef *e = upb_gmalloc(sizeof(*e));
459b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!e) return NULL;
460b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
461b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!upb_def_init(upb_enumdef_upcast_mutable(e), UPB_DEF_ENUM,
462b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                    &upb_enumdef_vtbl, owner)) {
463b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    goto err2;
464b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
465b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
466b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!upb_strtable_init(&e->ntoi, UPB_CTYPE_INT32)) goto err2;
467b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!upb_inttable_init(&e->iton, UPB_CTYPE_CSTR)) goto err1;
468b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return e;
469b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
470b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammererr1:
471b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_strtable_uninit(&e->ntoi);
472b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammererr2:
473b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_gfree(e);
474b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return NULL;
475b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
476b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
477b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerupb_enumdef *upb_enumdef_dup(const upb_enumdef *e, const void *owner) {
478b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_enum_iter i;
479b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_enumdef *new_e = upb_enumdef_new(owner);
480b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!new_e) return NULL;
481b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for(upb_enum_begin(&i, e); !upb_enum_done(&i); upb_enum_next(&i)) {
482b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    bool success = upb_enumdef_addval(
483b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        new_e, upb_enum_iter_name(&i),upb_enum_iter_number(&i), NULL);
484b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (!success) {
485b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_enumdef_unref(new_e, owner);
486b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return NULL;
487b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
488b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
489b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return new_e;
490b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
491b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
492b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_enumdef_freeze(upb_enumdef *e, upb_status *status) {
493b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_def *d = upb_enumdef_upcast_mutable(e);
494b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_def_freeze(&d, 1, status);
495b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
496b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
497b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst char *upb_enumdef_fullname(const upb_enumdef *e) {
498b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_def_fullname(upb_enumdef_upcast(e));
499b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
500b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
501b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst char *upb_enumdef_name(const upb_enumdef *e) {
502b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_def_name(upb_enumdef_upcast(e));
503b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
504b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
505b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_enumdef_setfullname(upb_enumdef *e, const char *fullname,
506b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                             upb_status *s) {
507b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_def_setfullname(upb_enumdef_upcast_mutable(e), fullname, s);
508b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
509b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
510b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_enumdef_addval(upb_enumdef *e, const char *name, int32_t num,
511b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                        upb_status *status) {
512b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  char *name2;
513b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
514b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!upb_isident(name, strlen(name), false, status)) {
515b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
516b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
517b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
518b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upb_enumdef_ntoiz(e, name, NULL)) {
519b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_status_seterrf(status, "name '%s' is already defined", name);
520b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
521b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
522b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
523b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!upb_strtable_insert(&e->ntoi, name, upb_value_int32(num))) {
524b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_status_seterrmsg(status, "out of memory");
525b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
526b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
527b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
528b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!upb_inttable_lookup(&e->iton, num, NULL)) {
529b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    name2 = upb_gstrdup(name);
530b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (!name2 || !upb_inttable_insert(&e->iton, num, upb_value_cstr(name2))) {
531b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_status_seterrmsg(status, "out of memory");
532b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_strtable_remove(&e->ntoi, name, NULL);
533b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return false;
534b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
535b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
536b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
537b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upb_enumdef_numvals(e) == 1) {
538b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    bool ok = upb_enumdef_setdefault(e, num, NULL);
539b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    UPB_ASSERT_VAR(ok, ok);
540b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
541b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
542b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
543b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
544b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
545b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerint32_t upb_enumdef_default(const upb_enumdef *e) {
546b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(upb_enumdef_iton(e, e->defaultval));
547b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return e->defaultval;
548b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
549b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
550b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_enumdef_setdefault(upb_enumdef *e, int32_t val, upb_status *s) {
551b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(!upb_enumdef_isfrozen(e));
552b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!upb_enumdef_iton(e, val)) {
553b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_status_seterrf(s, "number '%d' is not in the enum.", val);
554b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
555b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
556b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  e->defaultval = val;
557b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
558b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
559b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
560b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerint upb_enumdef_numvals(const upb_enumdef *e) {
561b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_strtable_count(&e->ntoi);
562b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
563b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
564b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_enum_begin(upb_enum_iter *i, const upb_enumdef *e) {
565b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* We iterate over the ntoi table, to account for duplicate numbers. */
566b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_strtable_begin(i, &e->ntoi);
567b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
568b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
569b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_enum_next(upb_enum_iter *iter) { upb_strtable_next(iter); }
570b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_enum_done(upb_enum_iter *iter) { return upb_strtable_done(iter); }
571b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
572b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_enumdef_ntoi(const upb_enumdef *def, const char *name,
573b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                      size_t len, int32_t *num) {
574b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_value v;
575b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!upb_strtable_lookup2(&def->ntoi, name, len, &v)) {
576b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
577b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
578b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (num) *num = upb_value_getint32(v);
579b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
580b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
581b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
582b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst char *upb_enumdef_iton(const upb_enumdef *def, int32_t num) {
583b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_value v;
584b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_inttable_lookup32(&def->iton, num, &v) ?
585b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_value_getcstr(v) : NULL;
586b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
587b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
588b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst char *upb_enum_iter_name(upb_enum_iter *iter) {
589b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_strtable_iter_key(iter);
590b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
591b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
592b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerint32_t upb_enum_iter_number(upb_enum_iter *iter) {
593b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_value_getint32(upb_strtable_iter_value(iter));
594b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
595b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
596b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
597b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* upb_fielddef ***************************************************************/
598b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
599b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void upb_fielddef_init_default(upb_fielddef *f);
600b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
601b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void upb_fielddef_uninit_default(upb_fielddef *f) {
602b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (f->type_is_set_ && f->default_is_string && f->defaultval.bytes)
603b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    freestr(f->defaultval.bytes);
604b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
605b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
606b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst char *upb_fielddef_fullname(const upb_fielddef *e) {
607b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_def_fullname(upb_fielddef_upcast(e));
608b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
609b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
610b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void visitfield(const upb_refcounted *r, upb_refcounted_visit *visit,
611b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                       void *closure) {
612b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const upb_fielddef *f = (const upb_fielddef*)r;
613b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upb_fielddef_containingtype(f)) {
614b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    visit(r, upb_msgdef_upcast2(upb_fielddef_containingtype(f)), closure);
615b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
616b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upb_fielddef_containingoneof(f)) {
617b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    visit(r, upb_oneofdef_upcast(upb_fielddef_containingoneof(f)), closure);
618b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
619b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upb_fielddef_subdef(f)) {
620b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    visit(r, upb_def_upcast(upb_fielddef_subdef(f)), closure);
621b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
622b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
623b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
624b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void freefield(upb_refcounted *r) {
625b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_fielddef *f = (upb_fielddef*)r;
626b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_fielddef_uninit_default(f);
627b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (f->subdef_is_symbolic)
628b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_gfree(f->sub.name);
629b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_def_uninit(upb_fielddef_upcast_mutable(f));
630b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_gfree(f);
631b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
632b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
633b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic const char *enumdefaultstr(const upb_fielddef *f) {
634b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const upb_enumdef *e;
635b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(f->type_is_set_ && f->type_ == UPB_TYPE_ENUM);
636b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  e = upb_fielddef_enumsubdef(f);
637b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (f->default_is_string && f->defaultval.bytes) {
638b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Default was explicitly set as a string. */
639b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    str_t *s = f->defaultval.bytes;
640b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return s->str;
641b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else if (e) {
642b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (!f->default_is_string) {
643b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      /* Default was explicitly set as an integer; look it up in enumdef. */
644b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      const char *name = upb_enumdef_iton(e, f->defaultval.sint);
645b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (name) {
646b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        return name;
647b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
648b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    } else {
649b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      /* Default is completely unset; pull enumdef default. */
650b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (upb_enumdef_numvals(e) > 0) {
651b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        const char *name = upb_enumdef_iton(e, upb_enumdef_default(e));
652b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        assert(name);
653b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        return name;
654b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
655b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
656b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
657b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return NULL;
658b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
659b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
660b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool enumdefaultint32(const upb_fielddef *f, int32_t *val) {
661b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const upb_enumdef *e;
662b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(f->type_is_set_ && f->type_ == UPB_TYPE_ENUM);
663b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  e = upb_fielddef_enumsubdef(f);
664b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!f->default_is_string) {
665b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Default was explicitly set as an integer. */
666b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    *val = f->defaultval.sint;
667b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return true;
668b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else if (e) {
669b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (f->defaultval.bytes) {
670b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      /* Default was explicitly set as a str; try to lookup corresponding int. */
671b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      str_t *s = f->defaultval.bytes;
672b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (upb_enumdef_ntoiz(e, s->str, val)) {
673b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        return true;
674b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
675b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    } else {
676b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      /* Default is unset; try to pull in enumdef default. */
677b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (upb_enumdef_numvals(e) > 0) {
678b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        *val = upb_enumdef_default(e);
679b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        return true;
680b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
681b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
682b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
683b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return false;
684b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
685b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
686b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst struct upb_refcounted_vtbl upb_fielddef_vtbl = {visitfield, freefield};
687b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
688b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerupb_fielddef *upb_fielddef_new(const void *o) {
689b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_fielddef *f = upb_gmalloc(sizeof(*f));
690b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!f) return NULL;
691b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!upb_def_init(upb_fielddef_upcast_mutable(f), UPB_DEF_FIELD,
692b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                    &upb_fielddef_vtbl, o)) {
693b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_gfree(f);
694b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return NULL;
695b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
696b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  f->msg.def = NULL;
697b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  f->sub.def = NULL;
698b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  f->oneof = NULL;
699b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  f->subdef_is_symbolic = false;
700b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  f->msg_is_symbolic = false;
701b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  f->label_ = UPB_LABEL_OPTIONAL;
702b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  f->type_ = UPB_TYPE_INT32;
703b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  f->number_ = 0;
704b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  f->type_is_set_ = false;
705b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  f->tagdelim = false;
706b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  f->is_extension_ = false;
707b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  f->lazy_ = false;
708b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  f->packed_ = true;
709b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
710b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* For the moment we default this to UPB_INTFMT_VARIABLE, since it will work
711b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * with all integer types and is in some since more "default" since the most
712b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * normal-looking proto2 types int32/int64/uint32/uint64 use variable.
713b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   *
714b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * Other options to consider:
715b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * - there is no default; users must set this manually (like type).
716b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * - default signed integers to UPB_INTFMT_ZIGZAG, since it's more likely to
717b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   *   be an optimal default for signed integers. */
718b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  f->intfmt = UPB_INTFMT_VARIABLE;
719b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return f;
720b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
721b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
722b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerupb_fielddef *upb_fielddef_dup(const upb_fielddef *f, const void *owner) {
723b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const char *srcname;
724b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_fielddef *newf = upb_fielddef_new(owner);
725b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!newf) return NULL;
726b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_fielddef_settype(newf, upb_fielddef_type(f));
727b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_fielddef_setlabel(newf, upb_fielddef_label(f));
728b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_fielddef_setnumber(newf, upb_fielddef_number(f), NULL);
729b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_fielddef_setname(newf, upb_fielddef_name(f), NULL);
730b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (f->default_is_string && f->defaultval.bytes) {
731b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    str_t *s = f->defaultval.bytes;
732b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_fielddef_setdefaultstr(newf, s->str, s->len, NULL);
733b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
734b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    newf->default_is_string = f->default_is_string;
735b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    newf->defaultval = f->defaultval;
736b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
737b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
738b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (f->subdef_is_symbolic) {
739b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    srcname = f->sub.name;  /* Might be NULL. */
740b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
741b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    srcname = f->sub.def ? upb_def_fullname(f->sub.def) : NULL;
742b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
743b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (srcname) {
744b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    char *newname = upb_gmalloc(strlen(f->sub.def->fullname) + 2);
745b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (!newname) {
746b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_fielddef_unref(newf, owner);
747b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return NULL;
748b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
749b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    strcpy(newname, ".");
750b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    strcat(newname, f->sub.def->fullname);
751b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_fielddef_setsubdefname(newf, newname, NULL);
752b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_gfree(newname);
753b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
754b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
755b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return newf;
756b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
757b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
758b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_fielddef_typeisset(const upb_fielddef *f) {
759b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return f->type_is_set_;
760b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
761b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
762b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerupb_fieldtype_t upb_fielddef_type(const upb_fielddef *f) {
763b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(f->type_is_set_);
764b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return f->type_;
765b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
766b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
767b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammeruint32_t upb_fielddef_index(const upb_fielddef *f) {
768b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return f->index_;
769b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
770b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
771b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerupb_label_t upb_fielddef_label(const upb_fielddef *f) {
772b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return f->label_;
773b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
774b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
775b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerupb_intfmt_t upb_fielddef_intfmt(const upb_fielddef *f) {
776b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return f->intfmt;
777b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
778b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
779b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_fielddef_istagdelim(const upb_fielddef *f) {
780b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return f->tagdelim;
781b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
782b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
783b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammeruint32_t upb_fielddef_number(const upb_fielddef *f) {
784b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return f->number_;
785b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
786b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
787b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_fielddef_isextension(const upb_fielddef *f) {
788b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return f->is_extension_;
789b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
790b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
791b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_fielddef_lazy(const upb_fielddef *f) {
792b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return f->lazy_;
793b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
794b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
795b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_fielddef_packed(const upb_fielddef *f) {
796b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return f->packed_;
797b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
798b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
799b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst char *upb_fielddef_name(const upb_fielddef *f) {
800b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_def_fullname(upb_fielddef_upcast(f));
801b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
802b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
803b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammersize_t upb_fielddef_getjsonname(const upb_fielddef *f, char *buf, size_t len) {
804b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const char *name = upb_fielddef_name(f);
805b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  size_t src, dst = 0;
806b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bool ucase_next = false;
807b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
808b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#define WRITE(byte) \
809b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  ++dst; \
810b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (dst < len) buf[dst - 1] = byte; \
811b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  else if (dst == len) buf[dst - 1] = '\0'
812b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
813b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!name) {
814b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    WRITE('\0');
815b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return 0;
816b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
817b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
818b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Implement the transformation as described in the spec:
819b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   *   1. upper case all letters after an underscore.
820b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   *   2. remove all underscores.
821b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   */
822b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for (src = 0; name[src]; src++) {
823b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (name[src] == '_') {
824b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      ucase_next = true;
825b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      continue;
826b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
827b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
828b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (ucase_next) {
829b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      WRITE(toupper(name[src]));
830b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      ucase_next = false;
831b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    } else {
832b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      WRITE(name[src]);
833b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
834b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
835b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
836b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  WRITE('\0');
837b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return dst;
838b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
839b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#undef WRITE
840b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
841b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
842b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_msgdef *upb_fielddef_containingtype(const upb_fielddef *f) {
843b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return f->msg_is_symbolic ? NULL : f->msg.def;
844b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
845b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
846b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_oneofdef *upb_fielddef_containingoneof(const upb_fielddef *f) {
847b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return f->oneof;
848b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
849b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
850b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerupb_msgdef *upb_fielddef_containingtype_mutable(upb_fielddef *f) {
851b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return (upb_msgdef*)upb_fielddef_containingtype(f);
852b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
853b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
854b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst char *upb_fielddef_containingtypename(upb_fielddef *f) {
855b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return f->msg_is_symbolic ? f->msg.name : NULL;
856b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
857b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
858b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void release_containingtype(upb_fielddef *f) {
859b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (f->msg_is_symbolic) upb_gfree(f->msg.name);
860b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
861b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
862b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_fielddef_setcontainingtypename(upb_fielddef *f, const char *name,
863b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                        upb_status *s) {
864b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  char *name_copy;
865b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(!upb_fielddef_isfrozen(f));
866b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upb_fielddef_containingtype(f)) {
867b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_status_seterrmsg(s, "field has already been added to a message.");
868b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
869b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
870b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* TODO: validate name (upb_isident() doesn't quite work atm because this name
871b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * may have a leading "."). */
872b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
873b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  name_copy = upb_gstrdup(name);
874b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!name_copy) {
875b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_upberr_setoom(s);
876b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
877b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
878b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
879b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  release_containingtype(f);
880b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  f->msg.name = name_copy;
881b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  f->msg_is_symbolic = true;
882b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
883b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
884b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
885b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_fielddef_setname(upb_fielddef *f, const char *name, upb_status *s) {
886b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upb_fielddef_containingtype(f) || upb_fielddef_containingoneof(f)) {
887b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_status_seterrmsg(s, "Already added to message or oneof");
888b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
889b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
890b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_def_setfullname(upb_fielddef_upcast_mutable(f), name, s);
891b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
892b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
893b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void chkdefaulttype(const upb_fielddef *f, upb_fieldtype_t type) {
894b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(f);
895b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(type);
896b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(f->type_is_set_ && upb_fielddef_type(f) == type);
897b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
898b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
899b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerint64_t upb_fielddef_defaultint64(const upb_fielddef *f) {
900b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  chkdefaulttype(f, UPB_TYPE_INT64);
901b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return f->defaultval.sint;
902b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
903b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
904b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerint32_t upb_fielddef_defaultint32(const upb_fielddef *f) {
905b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (f->type_is_set_ && upb_fielddef_type(f) == UPB_TYPE_ENUM) {
906b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    int32_t val;
907b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    bool ok = enumdefaultint32(f, &val);
908b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    UPB_ASSERT_VAR(ok, ok);
909b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return val;
910b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
911b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    chkdefaulttype(f, UPB_TYPE_INT32);
912b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return f->defaultval.sint;
913b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
914b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
915b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
916b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammeruint64_t upb_fielddef_defaultuint64(const upb_fielddef *f) {
917b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  chkdefaulttype(f, UPB_TYPE_UINT64);
918b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return f->defaultval.uint;
919b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
920b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
921b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammeruint32_t upb_fielddef_defaultuint32(const upb_fielddef *f) {
922b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  chkdefaulttype(f, UPB_TYPE_UINT32);
923b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return f->defaultval.uint;
924b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
925b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
926b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_fielddef_defaultbool(const upb_fielddef *f) {
927b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  chkdefaulttype(f, UPB_TYPE_BOOL);
928b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return f->defaultval.uint;
929b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
930b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
931b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerfloat upb_fielddef_defaultfloat(const upb_fielddef *f) {
932b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  chkdefaulttype(f, UPB_TYPE_FLOAT);
933b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return f->defaultval.flt;
934b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
935b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
936b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerdouble upb_fielddef_defaultdouble(const upb_fielddef *f) {
937b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  chkdefaulttype(f, UPB_TYPE_DOUBLE);
938b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return f->defaultval.dbl;
939b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
940b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
941b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst char *upb_fielddef_defaultstr(const upb_fielddef *f, size_t *len) {
942b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(f->type_is_set_);
943b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(upb_fielddef_type(f) == UPB_TYPE_STRING ||
944b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer         upb_fielddef_type(f) == UPB_TYPE_BYTES ||
945b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer         upb_fielddef_type(f) == UPB_TYPE_ENUM);
946b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
947b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upb_fielddef_type(f) == UPB_TYPE_ENUM) {
948b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    const char *ret = enumdefaultstr(f);
949b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    assert(ret);
950b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Enum defaults can't have embedded NULLs. */
951b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (len) *len = strlen(ret);
952b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return ret;
953b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
954b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
955b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (f->default_is_string) {
956b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    str_t *str = f->defaultval.bytes;
957b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (len) *len = str->len;
958b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return str->str;
959b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
960b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
961b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return NULL;
962b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
963b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
964b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void upb_fielddef_init_default(upb_fielddef *f) {
965b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  f->default_is_string = false;
966b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  switch (upb_fielddef_type(f)) {
967b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_DOUBLE: f->defaultval.dbl = 0; break;
968b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_FLOAT: f->defaultval.flt = 0; break;
969b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_INT32:
970b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_INT64: f->defaultval.sint = 0; break;
971b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_UINT64:
972b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_UINT32:
973b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_BOOL: f->defaultval.uint = 0; break;
974b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_STRING:
975b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_BYTES:
976b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      f->defaultval.bytes = newstr("", 0);
977b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      f->default_is_string = true;
978b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
979b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_MESSAGE: break;
980b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_ENUM:
981b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      /* This is our special sentinel that indicates "not set" for an enum. */
982b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      f->default_is_string = true;
983b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      f->defaultval.bytes = NULL;
984b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
985b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
986b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
987b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
988b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_def *upb_fielddef_subdef(const upb_fielddef *f) {
989b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return f->subdef_is_symbolic ? NULL : f->sub.def;
990b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
991b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
992b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_msgdef *upb_fielddef_msgsubdef(const upb_fielddef *f) {
993b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const upb_def *def = upb_fielddef_subdef(f);
994b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return def ? upb_dyncast_msgdef(def) : NULL;
995b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
996b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
997b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_enumdef *upb_fielddef_enumsubdef(const upb_fielddef *f) {
998b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const upb_def *def = upb_fielddef_subdef(f);
999b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return def ? upb_dyncast_enumdef(def) : NULL;
1000b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1001b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1002b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerupb_def *upb_fielddef_subdef_mutable(upb_fielddef *f) {
1003b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return (upb_def*)upb_fielddef_subdef(f);
1004b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1005b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1006b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst char *upb_fielddef_subdefname(const upb_fielddef *f) {
1007b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (f->subdef_is_symbolic) {
1008b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return f->sub.name;
1009b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else if (f->sub.def) {
1010b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return upb_def_fullname(f->sub.def);
1011b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
1012b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return NULL;
1013b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
1014b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1015b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1016b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_fielddef_setnumber(upb_fielddef *f, uint32_t number, upb_status *s) {
1017b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upb_fielddef_containingtype(f)) {
1018b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_status_seterrmsg(
1019b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        s, "cannot change field number after adding to a message");
1020b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
1021b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
1022b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (number == 0 || number > UPB_MAX_FIELDNUMBER) {
1023b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_status_seterrf(s, "invalid field number (%u)", number);
1024b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
1025b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
1026b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  f->number_ = number;
1027b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
1028b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1029b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1030b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_fielddef_settype(upb_fielddef *f, upb_fieldtype_t type) {
1031b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(!upb_fielddef_isfrozen(f));
1032b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(upb_fielddef_checktype(type));
1033b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_fielddef_uninit_default(f);
1034b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  f->type_ = type;
1035b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  f->type_is_set_ = true;
1036b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_fielddef_init_default(f);
1037b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1038b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1039b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_fielddef_setdescriptortype(upb_fielddef *f, int type) {
1040b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(!upb_fielddef_isfrozen(f));
1041b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  switch (type) {
1042b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_DESCRIPTOR_TYPE_DOUBLE:
1043b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_fielddef_settype(f, UPB_TYPE_DOUBLE);
1044b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
1045b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_DESCRIPTOR_TYPE_FLOAT:
1046b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_fielddef_settype(f, UPB_TYPE_FLOAT);
1047b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
1048b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_DESCRIPTOR_TYPE_INT64:
1049b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_DESCRIPTOR_TYPE_SFIXED64:
1050b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_DESCRIPTOR_TYPE_SINT64:
1051b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_fielddef_settype(f, UPB_TYPE_INT64);
1052b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
1053b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_DESCRIPTOR_TYPE_UINT64:
1054b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_DESCRIPTOR_TYPE_FIXED64:
1055b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_fielddef_settype(f, UPB_TYPE_UINT64);
1056b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
1057b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_DESCRIPTOR_TYPE_INT32:
1058b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_DESCRIPTOR_TYPE_SFIXED32:
1059b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_DESCRIPTOR_TYPE_SINT32:
1060b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_fielddef_settype(f, UPB_TYPE_INT32);
1061b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
1062b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_DESCRIPTOR_TYPE_UINT32:
1063b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_DESCRIPTOR_TYPE_FIXED32:
1064b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_fielddef_settype(f, UPB_TYPE_UINT32);
1065b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
1066b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_DESCRIPTOR_TYPE_BOOL:
1067b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_fielddef_settype(f, UPB_TYPE_BOOL);
1068b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
1069b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_DESCRIPTOR_TYPE_STRING:
1070b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_fielddef_settype(f, UPB_TYPE_STRING);
1071b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
1072b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_DESCRIPTOR_TYPE_BYTES:
1073b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_fielddef_settype(f, UPB_TYPE_BYTES);
1074b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
1075b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_DESCRIPTOR_TYPE_GROUP:
1076b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_DESCRIPTOR_TYPE_MESSAGE:
1077b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_fielddef_settype(f, UPB_TYPE_MESSAGE);
1078b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
1079b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_DESCRIPTOR_TYPE_ENUM:
1080b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_fielddef_settype(f, UPB_TYPE_ENUM);
1081b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
1082b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    default: assert(false);
1083b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
1084b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1085b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (type == UPB_DESCRIPTOR_TYPE_FIXED64 ||
1086b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      type == UPB_DESCRIPTOR_TYPE_FIXED32 ||
1087b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      type == UPB_DESCRIPTOR_TYPE_SFIXED64 ||
1088b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      type == UPB_DESCRIPTOR_TYPE_SFIXED32) {
1089b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_fielddef_setintfmt(f, UPB_INTFMT_FIXED);
1090b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else if (type == UPB_DESCRIPTOR_TYPE_SINT64 ||
1091b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer             type == UPB_DESCRIPTOR_TYPE_SINT32) {
1092b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_fielddef_setintfmt(f, UPB_INTFMT_ZIGZAG);
1093b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
1094b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_fielddef_setintfmt(f, UPB_INTFMT_VARIABLE);
1095b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
1096b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1097b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_fielddef_settagdelim(f, type == UPB_DESCRIPTOR_TYPE_GROUP);
1098b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1099b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1100b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerupb_descriptortype_t upb_fielddef_descriptortype(const upb_fielddef *f) {
1101b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  switch (upb_fielddef_type(f)) {
1102b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_FLOAT:  return UPB_DESCRIPTOR_TYPE_FLOAT;
1103b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_DOUBLE: return UPB_DESCRIPTOR_TYPE_DOUBLE;
1104b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_BOOL:   return UPB_DESCRIPTOR_TYPE_BOOL;
1105b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_STRING: return UPB_DESCRIPTOR_TYPE_STRING;
1106b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_BYTES:  return UPB_DESCRIPTOR_TYPE_BYTES;
1107b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_ENUM:   return UPB_DESCRIPTOR_TYPE_ENUM;
1108b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_INT32:
1109b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      switch (upb_fielddef_intfmt(f)) {
1110b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        case UPB_INTFMT_VARIABLE: return UPB_DESCRIPTOR_TYPE_INT32;
1111b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        case UPB_INTFMT_FIXED:    return UPB_DESCRIPTOR_TYPE_SFIXED32;
1112b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        case UPB_INTFMT_ZIGZAG:   return UPB_DESCRIPTOR_TYPE_SINT32;
1113b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
1114b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_INT64:
1115b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      switch (upb_fielddef_intfmt(f)) {
1116b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        case UPB_INTFMT_VARIABLE: return UPB_DESCRIPTOR_TYPE_INT64;
1117b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        case UPB_INTFMT_FIXED:    return UPB_DESCRIPTOR_TYPE_SFIXED64;
1118b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        case UPB_INTFMT_ZIGZAG:   return UPB_DESCRIPTOR_TYPE_SINT64;
1119b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
1120b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_UINT32:
1121b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      switch (upb_fielddef_intfmt(f)) {
1122b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        case UPB_INTFMT_VARIABLE: return UPB_DESCRIPTOR_TYPE_UINT32;
1123b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        case UPB_INTFMT_FIXED:    return UPB_DESCRIPTOR_TYPE_FIXED32;
1124b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        case UPB_INTFMT_ZIGZAG:   return -1;
1125b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
1126b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_UINT64:
1127b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      switch (upb_fielddef_intfmt(f)) {
1128b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        case UPB_INTFMT_VARIABLE: return UPB_DESCRIPTOR_TYPE_UINT64;
1129b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        case UPB_INTFMT_FIXED:    return UPB_DESCRIPTOR_TYPE_FIXED64;
1130b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        case UPB_INTFMT_ZIGZAG:   return -1;
1131b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
1132b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_MESSAGE:
1133b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return upb_fielddef_istagdelim(f) ?
1134b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          UPB_DESCRIPTOR_TYPE_GROUP : UPB_DESCRIPTOR_TYPE_MESSAGE;
1135b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
1136b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return 0;
1137b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1138b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1139b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_fielddef_setisextension(upb_fielddef *f, bool is_extension) {
1140b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(!upb_fielddef_isfrozen(f));
1141b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  f->is_extension_ = is_extension;
1142b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1143b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1144b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_fielddef_setlazy(upb_fielddef *f, bool lazy) {
1145b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(!upb_fielddef_isfrozen(f));
1146b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  f->lazy_ = lazy;
1147b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1148b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1149b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_fielddef_setpacked(upb_fielddef *f, bool packed) {
1150b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(!upb_fielddef_isfrozen(f));
1151b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  f->packed_ = packed;
1152b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1153b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1154b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_fielddef_setlabel(upb_fielddef *f, upb_label_t label) {
1155b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(!upb_fielddef_isfrozen(f));
1156b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(upb_fielddef_checklabel(label));
1157b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  f->label_ = label;
1158b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1159b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1160b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_fielddef_setintfmt(upb_fielddef *f, upb_intfmt_t fmt) {
1161b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(!upb_fielddef_isfrozen(f));
1162b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(upb_fielddef_checkintfmt(fmt));
1163b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  f->intfmt = fmt;
1164b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1165b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1166b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_fielddef_settagdelim(upb_fielddef *f, bool tag_delim) {
1167b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(!upb_fielddef_isfrozen(f));
1168b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  f->tagdelim = tag_delim;
1169b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  f->tagdelim = tag_delim;
1170b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1171b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1172b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool checksetdefault(upb_fielddef *f, upb_fieldtype_t type) {
1173b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!f->type_is_set_ || upb_fielddef_isfrozen(f) ||
1174b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_fielddef_type(f) != type) {
1175b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    assert(false);
1176b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
1177b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
1178b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (f->default_is_string) {
1179b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    str_t *s = f->defaultval.bytes;
1180b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    assert(s || type == UPB_TYPE_ENUM);
1181b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (s) freestr(s);
1182b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
1183b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  f->default_is_string = false;
1184b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
1185b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1186b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1187b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_fielddef_setdefaultint64(upb_fielddef *f, int64_t value) {
1188b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (checksetdefault(f, UPB_TYPE_INT64))
1189b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    f->defaultval.sint = value;
1190b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1191b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1192b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_fielddef_setdefaultint32(upb_fielddef *f, int32_t value) {
1193b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if ((upb_fielddef_type(f) == UPB_TYPE_ENUM &&
1194b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer       checksetdefault(f, UPB_TYPE_ENUM)) ||
1195b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      checksetdefault(f, UPB_TYPE_INT32)) {
1196b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    f->defaultval.sint = value;
1197b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
1198b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1199b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1200b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_fielddef_setdefaultuint64(upb_fielddef *f, uint64_t value) {
1201b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (checksetdefault(f, UPB_TYPE_UINT64))
1202b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    f->defaultval.uint = value;
1203b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1204b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1205b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_fielddef_setdefaultuint32(upb_fielddef *f, uint32_t value) {
1206b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (checksetdefault(f, UPB_TYPE_UINT32))
1207b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    f->defaultval.uint = value;
1208b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1209b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1210b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_fielddef_setdefaultbool(upb_fielddef *f, bool value) {
1211b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (checksetdefault(f, UPB_TYPE_BOOL))
1212b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    f->defaultval.uint = value;
1213b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1214b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1215b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_fielddef_setdefaultfloat(upb_fielddef *f, float value) {
1216b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (checksetdefault(f, UPB_TYPE_FLOAT))
1217b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    f->defaultval.flt = value;
1218b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1219b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1220b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_fielddef_setdefaultdouble(upb_fielddef *f, double value) {
1221b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (checksetdefault(f, UPB_TYPE_DOUBLE))
1222b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    f->defaultval.dbl = value;
1223b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1224b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1225b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_fielddef_setdefaultstr(upb_fielddef *f, const void *str, size_t len,
1226b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                upb_status *s) {
1227b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  str_t *str2;
1228b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(upb_fielddef_isstring(f) || f->type_ == UPB_TYPE_ENUM);
1229b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (f->type_ == UPB_TYPE_ENUM && !upb_isident(str, len, false, s))
1230b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
1231b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1232b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (f->default_is_string) {
1233b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    str_t *s = f->defaultval.bytes;
1234b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    assert(s || f->type_ == UPB_TYPE_ENUM);
1235b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (s) freestr(s);
1236b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
1237b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    assert(f->type_ == UPB_TYPE_ENUM);
1238b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
1239b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1240b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  str2 = newstr(str, len);
1241b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  f->defaultval.bytes = str2;
1242b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  f->default_is_string = true;
1243b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
1244b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1245b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1246b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_fielddef_setdefaultcstr(upb_fielddef *f, const char *str,
1247b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                 upb_status *s) {
1248b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(f->type_is_set_);
1249b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_fielddef_setdefaultstr(f, str, str ? strlen(str) : 0, s);
1250b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1251b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1252b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_fielddef_enumhasdefaultint32(const upb_fielddef *f) {
1253b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  int32_t val;
1254b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(f->type_is_set_ && f->type_ == UPB_TYPE_ENUM);
1255b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return enumdefaultint32(f, &val);
1256b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1257b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1258b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_fielddef_enumhasdefaultstr(const upb_fielddef *f) {
1259b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(f->type_is_set_ && f->type_ == UPB_TYPE_ENUM);
1260b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return enumdefaultstr(f) != NULL;
1261b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1262b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1263b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool upb_subdef_typecheck(upb_fielddef *f, const upb_def *subdef,
1264b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                 upb_status *s) {
1265b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (f->type_ == UPB_TYPE_MESSAGE) {
1266b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (upb_dyncast_msgdef(subdef)) return true;
1267b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_status_seterrmsg(s, "invalid subdef type for this submessage field");
1268b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
1269b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else if (f->type_ == UPB_TYPE_ENUM) {
1270b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (upb_dyncast_enumdef(subdef)) return true;
1271b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_status_seterrmsg(s, "invalid subdef type for this enum field");
1272b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
1273b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
1274b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_status_seterrmsg(s, "only message and enum fields can have a subdef");
1275b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
1276b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
1277b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1278b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1279b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void release_subdef(upb_fielddef *f) {
1280b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (f->subdef_is_symbolic) {
1281b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_gfree(f->sub.name);
1282b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else if (f->sub.def) {
1283b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_unref2(f->sub.def, f);
1284b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
1285b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1286b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1287b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_fielddef_setsubdef(upb_fielddef *f, const upb_def *subdef,
1288b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                            upb_status *s) {
1289b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(!upb_fielddef_isfrozen(f));
1290b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(upb_fielddef_hassubdef(f));
1291b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (subdef && !upb_subdef_typecheck(f, subdef, s)) return false;
1292b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  release_subdef(f);
1293b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  f->sub.def = subdef;
1294b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  f->subdef_is_symbolic = false;
1295b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (f->sub.def) upb_ref2(f->sub.def, f);
1296b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
1297b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1298b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1299b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_fielddef_setmsgsubdef(upb_fielddef *f, const upb_msgdef *subdef,
1300b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                               upb_status *s) {
1301b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_fielddef_setsubdef(f, upb_msgdef_upcast(subdef), s);
1302b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1303b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1304b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_fielddef_setenumsubdef(upb_fielddef *f, const upb_enumdef *subdef,
1305b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                upb_status *s) {
1306b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_fielddef_setsubdef(f, upb_enumdef_upcast(subdef), s);
1307b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1308b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1309b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_fielddef_setsubdefname(upb_fielddef *f, const char *name,
1310b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                upb_status *s) {
1311b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  char *name_copy;
1312b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(!upb_fielddef_isfrozen(f));
1313b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!upb_fielddef_hassubdef(f)) {
1314b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_status_seterrmsg(s, "field type does not accept a subdef");
1315b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
1316b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
1317b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1318b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  name_copy = upb_gstrdup(name);
1319b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!name_copy) {
1320b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_upberr_setoom(s);
1321b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
1322b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
1323b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1324b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* TODO: validate name (upb_isident() doesn't quite work atm because this name
1325b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * may have a leading "."). */
1326b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  release_subdef(f);
1327b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  f->sub.name = name_copy;
1328b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  f->subdef_is_symbolic = true;
1329b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
1330b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1331b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1332b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_fielddef_issubmsg(const upb_fielddef *f) {
1333b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_fielddef_type(f) == UPB_TYPE_MESSAGE;
1334b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1335b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1336b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_fielddef_isstring(const upb_fielddef *f) {
1337b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_fielddef_type(f) == UPB_TYPE_STRING ||
1338b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer         upb_fielddef_type(f) == UPB_TYPE_BYTES;
1339b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1340b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1341b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_fielddef_isseq(const upb_fielddef *f) {
1342b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_fielddef_label(f) == UPB_LABEL_REPEATED;
1343b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1344b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1345b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_fielddef_isprimitive(const upb_fielddef *f) {
1346b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return !upb_fielddef_isstring(f) && !upb_fielddef_issubmsg(f);
1347b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1348b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1349b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_fielddef_ismap(const upb_fielddef *f) {
1350b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_fielddef_isseq(f) && upb_fielddef_issubmsg(f) &&
1351b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer         upb_msgdef_mapentry(upb_fielddef_msgsubdef(f));
1352b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1353b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1354b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_fielddef_haspresence(const upb_fielddef *f) {
1355b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upb_fielddef_isseq(f)) return false;
1356b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upb_fielddef_issubmsg(f)) return true;
1357b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1358b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Primitive field: return true unless there is a message that specifies
1359b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * presence should not exist. */
1360b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (f->msg_is_symbolic || !f->msg.def) return true;
1361b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return f->msg.def->syntax == UPB_SYNTAX_PROTO2;
1362b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1363b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1364b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_fielddef_hassubdef(const upb_fielddef *f) {
1365b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_fielddef_issubmsg(f) || upb_fielddef_type(f) == UPB_TYPE_ENUM;
1366b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1367b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1368b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool between(int32_t x, int32_t low, int32_t high) {
1369b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return x >= low && x <= high;
1370b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1371b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1372b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_fielddef_checklabel(int32_t label) { return between(label, 1, 3); }
1373b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_fielddef_checktype(int32_t type) { return between(type, 1, 11); }
1374b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_fielddef_checkintfmt(int32_t fmt) { return between(fmt, 1, 3); }
1375b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1376b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_fielddef_checkdescriptortype(int32_t type) {
1377b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return between(type, 1, 18);
1378b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1379b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1380b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* upb_msgdef *****************************************************************/
1381b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1382b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void visitmsg(const upb_refcounted *r, upb_refcounted_visit *visit,
1383b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                     void *closure) {
1384b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_msg_oneof_iter o;
1385b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const upb_msgdef *m = (const upb_msgdef*)r;
1386b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_msg_field_iter i;
1387b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for(upb_msg_field_begin(&i, m);
1388b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      !upb_msg_field_done(&i);
1389b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_msg_field_next(&i)) {
1390b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_fielddef *f = upb_msg_iter_field(&i);
1391b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    visit(r, upb_fielddef_upcast2(f), closure);
1392b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
1393b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for(upb_msg_oneof_begin(&o, m);
1394b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      !upb_msg_oneof_done(&o);
1395b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_msg_oneof_next(&o)) {
1396b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_oneofdef *f = upb_msg_iter_oneof(&o);
1397b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    visit(r, upb_oneofdef_upcast(f), closure);
1398b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
1399b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1400b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1401b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void freemsg(upb_refcounted *r) {
1402b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_msgdef *m = (upb_msgdef*)r;
1403b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_strtable_uninit(&m->ntof);
1404b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_uninit(&m->itof);
1405b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_def_uninit(upb_msgdef_upcast_mutable(m));
1406b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_gfree(m);
1407b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1408b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1409b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst struct upb_refcounted_vtbl upb_msgdef_vtbl = {visitmsg, freemsg};
1410b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1411b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerupb_msgdef *upb_msgdef_new(const void *owner) {
1412b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_msgdef *m = upb_gmalloc(sizeof(*m));
1413b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!m) return NULL;
1414b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1415b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!upb_def_init(upb_msgdef_upcast_mutable(m), UPB_DEF_MSG, &upb_msgdef_vtbl,
1416b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                    owner)) {
1417b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    goto err2;
1418b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
1419b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1420b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!upb_inttable_init(&m->itof, UPB_CTYPE_PTR)) goto err2;
1421b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!upb_strtable_init(&m->ntof, UPB_CTYPE_PTR)) goto err1;
1422b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  m->map_entry = false;
1423b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  m->syntax = UPB_SYNTAX_PROTO2;
1424b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return m;
1425b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1426b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammererr1:
1427b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_uninit(&m->itof);
1428b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammererr2:
1429b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_gfree(m);
1430b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return NULL;
1431b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1432b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1433b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerupb_msgdef *upb_msgdef_dup(const upb_msgdef *m, const void *owner) {
1434b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bool ok;
1435b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_msg_field_iter i;
1436b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_msg_oneof_iter o;
1437b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1438b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_msgdef *newm = upb_msgdef_new(owner);
1439b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!newm) return NULL;
1440b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  ok = upb_def_setfullname(upb_msgdef_upcast_mutable(newm),
1441b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                           upb_def_fullname(upb_msgdef_upcast(m)),
1442b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                           NULL);
1443b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  newm->map_entry = m->map_entry;
1444b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  newm->syntax = m->syntax;
1445b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_ASSERT_VAR(ok, ok);
1446b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for(upb_msg_field_begin(&i, m);
1447b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      !upb_msg_field_done(&i);
1448b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_msg_field_next(&i)) {
1449b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_fielddef *f = upb_fielddef_dup(upb_msg_iter_field(&i), &f);
1450b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Fields in oneofs are dup'd below. */
1451b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (upb_fielddef_containingoneof(f)) continue;
1452b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (!f || !upb_msgdef_addfield(newm, f, &f, NULL)) {
1453b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_msgdef_unref(newm, owner);
1454b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return NULL;
1455b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
1456b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
1457b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for(upb_msg_oneof_begin(&o, m);
1458b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      !upb_msg_oneof_done(&o);
1459b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_msg_oneof_next(&o)) {
1460b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_oneofdef *f = upb_oneofdef_dup(upb_msg_iter_oneof(&o), &f);
1461b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (!f || !upb_msgdef_addoneof(newm, f, &f, NULL)) {
1462b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_msgdef_unref(newm, owner);
1463b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return NULL;
1464b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
1465b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
1466b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return newm;
1467b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1468b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1469b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_msgdef_freeze(upb_msgdef *m, upb_status *status) {
1470b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_def *d = upb_msgdef_upcast_mutable(m);
1471b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_def_freeze(&d, 1, status);
1472b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1473b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1474b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst char *upb_msgdef_fullname(const upb_msgdef *m) {
1475b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_def_fullname(upb_msgdef_upcast(m));
1476b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1477b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1478b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst char *upb_msgdef_name(const upb_msgdef *m) {
1479b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_def_name(upb_msgdef_upcast(m));
1480b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1481b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1482b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_msgdef_setfullname(upb_msgdef *m, const char *fullname,
1483b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                            upb_status *s) {
1484b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_def_setfullname(upb_msgdef_upcast_mutable(m), fullname, s);
1485b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1486b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1487b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_msgdef_setsyntax(upb_msgdef *m, upb_syntax_t syntax) {
1488b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (syntax != UPB_SYNTAX_PROTO2 && syntax != UPB_SYNTAX_PROTO3) {
1489b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
1490b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
1491b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1492b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  m->syntax = syntax;
1493b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
1494b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1495b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1496b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerupb_syntax_t upb_msgdef_syntax(const upb_msgdef *m) {
1497b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return m->syntax;
1498b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1499b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1500b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Helper: check that the field |f| is safe to add to msgdef |m|. Set an error
1501b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * on status |s| and return false if not. */
1502b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool check_field_add(const upb_msgdef *m, const upb_fielddef *f,
1503b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                            upb_status *s) {
1504b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upb_fielddef_containingtype(f) != NULL) {
1505b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_status_seterrmsg(s, "fielddef already belongs to a message");
1506b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
1507b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else if (upb_fielddef_name(f) == NULL || upb_fielddef_number(f) == 0) {
1508b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_status_seterrmsg(s, "field name or number were not set");
1509b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
1510b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else if (upb_msgdef_itof(m, upb_fielddef_number(f))) {
1511b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_status_seterrmsg(s, "duplicate field number");
1512b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
1513b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else if (upb_strtable_lookup(&m->ntof, upb_fielddef_name(f), NULL)) {
1514b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_status_seterrmsg(s, "name conflicts with existing field or oneof");
1515b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
1516b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
1517b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
1518b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1519b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1520b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void add_field(upb_msgdef *m, upb_fielddef *f, const void *ref_donor) {
1521b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  release_containingtype(f);
1522b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  f->msg.def = m;
1523b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  f->msg_is_symbolic = false;
1524b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_insert(&m->itof, upb_fielddef_number(f), upb_value_ptr(f));
1525b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_strtable_insert(&m->ntof, upb_fielddef_name(f), upb_value_ptr(f));
1526b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_ref2(f, m);
1527b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_ref2(m, f);
1528b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (ref_donor) upb_fielddef_unref(f, ref_donor);
1529b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1530b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1531b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_msgdef_addfield(upb_msgdef *m, upb_fielddef *f, const void *ref_donor,
1532b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                         upb_status *s) {
1533b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* TODO: extensions need to have a separate namespace, because proto2 allows a
1534b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * top-level extension (ie. one not in any package) to have the same name as a
1535b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * field from the message.
1536b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   *
1537b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * This also implies that there needs to be a separate lookup-by-name method
1538b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * for extensions.  It seems desirable for iteration to return both extensions
1539b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * and non-extensions though.
1540b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   *
1541b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * We also need to validate that the field number is in an extension range iff
1542b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * it is an extension.
1543b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   *
1544b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * This method is idempotent. Check if |f| is already part of this msgdef and
1545b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * return immediately if so. */
1546b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upb_fielddef_containingtype(f) == m) {
1547b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return true;
1548b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
1549b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1550b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Check constraints for all fields before performing any action. */
1551b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!check_field_add(m, f, s)) {
1552b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
1553b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else if (upb_fielddef_containingoneof(f) != NULL) {
1554b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Fields in a oneof can only be added by adding the oneof to the msgdef. */
1555b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_status_seterrmsg(s, "fielddef is part of a oneof");
1556b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
1557b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
1558b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1559b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Constraint checks ok, perform the action. */
1560b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  add_field(m, f, ref_donor);
1561b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
1562b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1563b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1564b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_msgdef_addoneof(upb_msgdef *m, upb_oneofdef *o, const void *ref_donor,
1565b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                         upb_status *s) {
1566b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_oneof_iter it;
1567b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1568b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Check various conditions that would prevent this oneof from being added. */
1569b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upb_oneofdef_containingtype(o)) {
1570b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_status_seterrmsg(s, "oneofdef already belongs to a message");
1571b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
1572b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else if (upb_oneofdef_name(o) == NULL) {
1573b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_status_seterrmsg(s, "oneofdef name was not set");
1574b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
1575b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else if (upb_strtable_lookup(&m->ntof, upb_oneofdef_name(o), NULL)) {
1576b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_status_seterrmsg(s, "name conflicts with existing field or oneof");
1577b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
1578b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
1579b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1580b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Check that all of the oneof's fields do not conflict with names or numbers
1581b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * of fields already in the message. */
1582b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for (upb_oneof_begin(&it, o); !upb_oneof_done(&it); upb_oneof_next(&it)) {
1583b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    const upb_fielddef *f = upb_oneof_iter_field(&it);
1584b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (!check_field_add(m, f, s)) {
1585b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return false;
1586b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
1587b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
1588b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1589b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Everything checks out -- commit now. */
1590b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1591b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Add oneof itself first. */
1592b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  o->parent = m;
1593b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_strtable_insert(&m->ntof, upb_oneofdef_name(o), upb_value_ptr(o));
1594b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_ref2(o, m);
1595b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_ref2(m, o);
1596b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1597b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Add each field of the oneof directly to the msgdef. */
1598b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for (upb_oneof_begin(&it, o); !upb_oneof_done(&it); upb_oneof_next(&it)) {
1599b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_fielddef *f = upb_oneof_iter_field(&it);
1600b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    add_field(m, f, NULL);
1601b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
1602b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1603b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (ref_donor) upb_oneofdef_unref(o, ref_donor);
1604b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1605b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
1606b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1607b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1608b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_fielddef *upb_msgdef_itof(const upb_msgdef *m, uint32_t i) {
1609b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_value val;
1610b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_inttable_lookup32(&m->itof, i, &val) ?
1611b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_value_getptr(val) : NULL;
1612b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1613b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1614b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_fielddef *upb_msgdef_ntof(const upb_msgdef *m, const char *name,
1615b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                    size_t len) {
1616b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_value val;
1617b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1618b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) {
1619b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return NULL;
1620b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
1621b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1622b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_trygetfield(upb_value_getptr(val));
1623b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1624b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1625b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_oneofdef *upb_msgdef_ntoo(const upb_msgdef *m, const char *name,
1626b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                    size_t len) {
1627b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_value val;
1628b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1629b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) {
1630b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return NULL;
1631b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
1632b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1633b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_trygetoneof(upb_value_getptr(val));
1634b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1635b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1636b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_msgdef_lookupname(const upb_msgdef *m, const char *name, size_t len,
1637b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                           const upb_fielddef **f, const upb_oneofdef **o) {
1638b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_value val;
1639b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1640b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) {
1641b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
1642b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
1643b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1644b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  *o = upb_trygetoneof(upb_value_getptr(val));
1645b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  *f = upb_trygetfield(upb_value_getptr(val));
1646b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert((*o != NULL) ^ (*f != NULL));  /* Exactly one of the two should be set. */
1647b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
1648b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1649b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1650b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerint upb_msgdef_numfields(const upb_msgdef *m) {
1651b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* The number table contains only fields. */
1652b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_inttable_count(&m->itof);
1653b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1654b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1655b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerint upb_msgdef_numoneofs(const upb_msgdef *m) {
1656b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* The name table includes oneofs, and the number table does not. */
1657b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_strtable_count(&m->ntof) - upb_inttable_count(&m->itof);
1658b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1659b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1660b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_msgdef_setmapentry(upb_msgdef *m, bool map_entry) {
1661b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(!upb_msgdef_isfrozen(m));
1662b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  m->map_entry = map_entry;
1663b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1664b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1665b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_msgdef_mapentry(const upb_msgdef *m) {
1666b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return m->map_entry;
1667b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1668b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1669b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_msg_field_begin(upb_msg_field_iter *iter, const upb_msgdef *m) {
1670b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_begin(iter, &m->itof);
1671b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1672b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1673b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_msg_field_next(upb_msg_field_iter *iter) { upb_inttable_next(iter); }
1674b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1675b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_msg_field_done(const upb_msg_field_iter *iter) {
1676b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_inttable_done(iter);
1677b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1678b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1679b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerupb_fielddef *upb_msg_iter_field(const upb_msg_field_iter *iter) {
1680b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return (upb_fielddef*)upb_value_getptr(upb_inttable_iter_value(iter));
1681b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1682b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1683b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_msg_field_iter_setdone(upb_msg_field_iter *iter) {
1684b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_iter_setdone(iter);
1685b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1686b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1687b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_msg_oneof_begin(upb_msg_oneof_iter *iter, const upb_msgdef *m) {
1688b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_strtable_begin(iter, &m->ntof);
1689b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* We need to skip past any initial fields. */
1690b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  while (!upb_strtable_done(iter) &&
1691b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer         !upb_isoneof(upb_value_getptr(upb_strtable_iter_value(iter)))) {
1692b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_strtable_next(iter);
1693b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
1694b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1695b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1696b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_msg_oneof_next(upb_msg_oneof_iter *iter) {
1697b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* We need to skip past fields to return only oneofs. */
1698b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  do {
1699b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_strtable_next(iter);
1700b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } while (!upb_strtable_done(iter) &&
1701b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer           !upb_isoneof(upb_value_getptr(upb_strtable_iter_value(iter))));
1702b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1703b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1704b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_msg_oneof_done(const upb_msg_oneof_iter *iter) {
1705b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_strtable_done(iter);
1706b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1707b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1708b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerupb_oneofdef *upb_msg_iter_oneof(const upb_msg_oneof_iter *iter) {
1709b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return (upb_oneofdef*)upb_value_getptr(upb_strtable_iter_value(iter));
1710b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1711b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1712b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_msg_oneof_iter_setdone(upb_msg_oneof_iter *iter) {
1713b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_strtable_iter_setdone(iter);
1714b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1715b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1716b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* upb_oneofdef ***************************************************************/
1717b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1718b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void visitoneof(const upb_refcounted *r, upb_refcounted_visit *visit,
1719b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                       void *closure) {
1720b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const upb_oneofdef *o = (const upb_oneofdef*)r;
1721b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_oneof_iter i;
1722b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for (upb_oneof_begin(&i, o); !upb_oneof_done(&i); upb_oneof_next(&i)) {
1723b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    const upb_fielddef *f = upb_oneof_iter_field(&i);
1724b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    visit(r, upb_fielddef_upcast2(f), closure);
1725b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
1726b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (o->parent) {
1727b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    visit(r, upb_msgdef_upcast2(o->parent), closure);
1728b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
1729b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1730b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1731b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void freeoneof(upb_refcounted *r) {
1732b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_oneofdef *o = (upb_oneofdef*)r;
1733b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_strtable_uninit(&o->ntof);
1734b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_uninit(&o->itof);
1735b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_gfree((void*)o->name);
1736b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_gfree(o);
1737b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1738b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1739b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst struct upb_refcounted_vtbl upb_oneofdef_vtbl = {visitoneof, freeoneof};
1740b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1741b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerupb_oneofdef *upb_oneofdef_new(const void *owner) {
1742b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_oneofdef *o = upb_gmalloc(sizeof(*o));
1743b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1744b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!o) {
1745b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return NULL;
1746b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
1747b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1748b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  o->parent = NULL;
1749b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  o->name = NULL;
1750b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1751b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!upb_refcounted_init(upb_oneofdef_upcast_mutable(o), &upb_oneofdef_vtbl,
1752b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                           owner)) {
1753b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    goto err2;
1754b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
1755b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1756b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!upb_inttable_init(&o->itof, UPB_CTYPE_PTR)) goto err2;
1757b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!upb_strtable_init(&o->ntof, UPB_CTYPE_PTR)) goto err1;
1758b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1759b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return o;
1760b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1761b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammererr1:
1762b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_uninit(&o->itof);
1763b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammererr2:
1764b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_gfree(o);
1765b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return NULL;
1766b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1767b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1768b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerupb_oneofdef *upb_oneofdef_dup(const upb_oneofdef *o, const void *owner) {
1769b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bool ok;
1770b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_oneof_iter i;
1771b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_oneofdef *newo = upb_oneofdef_new(owner);
1772b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!newo) return NULL;
1773b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  ok = upb_oneofdef_setname(newo, upb_oneofdef_name(o), NULL);
1774b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_ASSERT_VAR(ok, ok);
1775b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for (upb_oneof_begin(&i, o); !upb_oneof_done(&i); upb_oneof_next(&i)) {
1776b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_fielddef *f = upb_fielddef_dup(upb_oneof_iter_field(&i), &f);
1777b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (!f || !upb_oneofdef_addfield(newo, f, &f, NULL)) {
1778b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_oneofdef_unref(newo, owner);
1779b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return NULL;
1780b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
1781b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
1782b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return newo;
1783b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1784b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1785b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst char *upb_oneofdef_name(const upb_oneofdef *o) { return o->name; }
1786b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1787b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_oneofdef_setname(upb_oneofdef *o, const char *name, upb_status *s) {
1788b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(!upb_oneofdef_isfrozen(o));
1789b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upb_oneofdef_containingtype(o)) {
1790b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_status_seterrmsg(s, "oneof already added to a message");
1791b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
1792b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
1793b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1794b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!upb_isident(name, strlen(name), true, s)) {
1795b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
1796b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
1797b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1798b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  name = upb_gstrdup(name);
1799b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!name) {
1800b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_status_seterrmsg(s, "One of memory");
1801b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
1802b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
1803b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1804b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_gfree((void*)o->name);
1805b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  o->name = name;
1806b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
1807b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1808b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1809b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_msgdef *upb_oneofdef_containingtype(const upb_oneofdef *o) {
1810b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return o->parent;
1811b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1812b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1813b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerint upb_oneofdef_numfields(const upb_oneofdef *o) {
1814b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_strtable_count(&o->ntof);
1815b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1816b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1817b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_oneofdef_addfield(upb_oneofdef *o, upb_fielddef *f,
1818b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                           const void *ref_donor,
1819b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                           upb_status *s) {
1820b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(!upb_oneofdef_isfrozen(o));
1821b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(!o->parent || !upb_msgdef_isfrozen(o->parent));
1822b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1823b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* This method is idempotent. Check if |f| is already part of this oneofdef
1824b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * and return immediately if so. */
1825b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upb_fielddef_containingoneof(f) == o) {
1826b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return true;
1827b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
1828b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1829b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* The field must have an OPTIONAL label. */
1830b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upb_fielddef_label(f) != UPB_LABEL_OPTIONAL) {
1831b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_status_seterrmsg(s, "fields in oneof must have OPTIONAL label");
1832b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
1833b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
1834b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1835b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Check that no field with this name or number exists already in the oneof.
1836b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * Also check that the field is not already part of a oneof. */
1837b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upb_fielddef_name(f) == NULL || upb_fielddef_number(f) == 0) {
1838b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_status_seterrmsg(s, "field name or number were not set");
1839b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
1840b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else if (upb_oneofdef_itof(o, upb_fielddef_number(f)) ||
1841b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer             upb_oneofdef_ntofz(o, upb_fielddef_name(f))) {
1842b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_status_seterrmsg(s, "duplicate field name or number");
1843b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
1844b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else if (upb_fielddef_containingoneof(f) != NULL) {
1845b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_status_seterrmsg(s, "fielddef already belongs to a oneof");
1846b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
1847b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
1848b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1849b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* We allow adding a field to the oneof either if the field is not part of a
1850b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * msgdef, or if it is and we are also part of the same msgdef. */
1851b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (o->parent == NULL) {
1852b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* If we're not in a msgdef, the field cannot be either. Otherwise we would
1853b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * need to magically add this oneof to a msgdef to remain consistent, which
1854b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * is surprising behavior. */
1855b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (upb_fielddef_containingtype(f) != NULL) {
1856b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_status_seterrmsg(s, "fielddef already belongs to a message, but "
1857b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                              "oneof does not");
1858b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return false;
1859b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
1860b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
1861b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* If we're in a msgdef, the user can add fields that either aren't in any
1862b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * msgdef (in which case they're added to our msgdef) or already a part of
1863b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * our msgdef. */
1864b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (upb_fielddef_containingtype(f) != NULL &&
1865b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_fielddef_containingtype(f) != o->parent) {
1866b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_status_seterrmsg(s, "fielddef belongs to a different message "
1867b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                              "than oneof");
1868b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return false;
1869b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
1870b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
1871b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1872b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Commit phase. First add the field to our parent msgdef, if any, because
1873b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * that may fail; then add the field to our own tables. */
1874b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1875b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (o->parent != NULL && upb_fielddef_containingtype(f) == NULL) {
1876b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (!upb_msgdef_addfield((upb_msgdef*)o->parent, f, NULL, s)) {
1877b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return false;
1878b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
1879b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
1880b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1881b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  release_containingtype(f);
1882b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  f->oneof = o;
1883b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_insert(&o->itof, upb_fielddef_number(f), upb_value_ptr(f));
1884b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_strtable_insert(&o->ntof, upb_fielddef_name(f), upb_value_ptr(f));
1885b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_ref2(f, o);
1886b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_ref2(o, f);
1887b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (ref_donor) upb_fielddef_unref(f, ref_donor);
1888b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1889b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
1890b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1891b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1892b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_fielddef *upb_oneofdef_ntof(const upb_oneofdef *o,
1893b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                      const char *name, size_t length) {
1894b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_value val;
1895b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_strtable_lookup2(&o->ntof, name, length, &val) ?
1896b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_value_getptr(val) : NULL;
1897b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1898b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1899b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_fielddef *upb_oneofdef_itof(const upb_oneofdef *o, uint32_t num) {
1900b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_value val;
1901b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_inttable_lookup32(&o->itof, num, &val) ?
1902b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_value_getptr(val) : NULL;
1903b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1904b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1905b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_oneof_begin(upb_oneof_iter *iter, const upb_oneofdef *o) {
1906b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_begin(iter, &o->itof);
1907b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1908b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1909b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_oneof_next(upb_oneof_iter *iter) {
1910b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_next(iter);
1911b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1912b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1913b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_oneof_done(upb_oneof_iter *iter) {
1914b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_inttable_done(iter);
1915b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1916b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1917b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerupb_fielddef *upb_oneof_iter_field(const upb_oneof_iter *iter) {
1918b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return (upb_fielddef*)upb_value_getptr(upb_inttable_iter_value(iter));
1919b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1920b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1921b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_oneof_iter_setdone(upb_oneof_iter *iter) {
1922b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_iter_setdone(iter);
1923b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1924b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1925b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* upb_filedef ****************************************************************/
1926b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1927b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void visitfiledef(const upb_refcounted *r, upb_refcounted_visit *visit,
1928b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                         void *closure) {
1929b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const upb_filedef *f = (const upb_filedef*)r;
1930b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  size_t i;
1931b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1932b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for(i = 0; i < upb_filedef_defcount(f); i++) {
1933b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    visit(r, upb_def_upcast(upb_filedef_def(f, i)), closure);
1934b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
1935b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1936b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1937b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void freefiledef(upb_refcounted *r) {
1938b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_filedef *f = (upb_filedef*)r;
1939b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  size_t i;
1940b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1941b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for(i = 0; i < upb_filedef_depcount(f); i++) {
1942b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_filedef_unref(upb_filedef_dep(f, i), f);
1943b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
1944b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1945b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_uninit(&f->defs);
1946b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_uninit(&f->deps);
1947b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_gfree((void*)f->name);
1948b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_gfree((void*)f->package);
1949b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_gfree(f);
1950b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1951b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1952b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst struct upb_refcounted_vtbl upb_filedef_vtbl = {visitfiledef, freefiledef};
1953b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1954b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerupb_filedef *upb_filedef_new(const void *owner) {
1955b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_filedef *f = upb_gmalloc(sizeof(*f));
1956b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1957b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!f) {
1958b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return NULL;
1959b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
1960b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1961b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  f->package = NULL;
1962b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  f->name = NULL;
1963b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  f->syntax = UPB_SYNTAX_PROTO2;
1964b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1965b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!upb_refcounted_init(upb_filedef_upcast_mutable(f), &upb_filedef_vtbl,
1966b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                           owner)) {
1967b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    goto err;
1968b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
1969b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1970b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!upb_inttable_init(&f->defs, UPB_CTYPE_CONSTPTR)) {
1971b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    goto err;
1972b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
1973b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1974b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!upb_inttable_init(&f->deps, UPB_CTYPE_CONSTPTR)) {
1975b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    goto err2;
1976b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
1977b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1978b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return f;
1979b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1980b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1981b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammererr2:
1982b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_uninit(&f->defs);
1983b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1984b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammererr:
1985b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_gfree(f);
1986b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return NULL;
1987b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1988b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1989b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst char *upb_filedef_name(const upb_filedef *f) {
1990b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return f->name;
1991b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1992b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1993b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst char *upb_filedef_package(const upb_filedef *f) {
1994b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return f->package;
1995b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
1996b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1997b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerupb_syntax_t upb_filedef_syntax(const upb_filedef *f) {
1998b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return f->syntax;
1999b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
2000b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2001b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammersize_t upb_filedef_defcount(const upb_filedef *f) {
2002b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_inttable_count(&f->defs);
2003b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
2004b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2005b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammersize_t upb_filedef_depcount(const upb_filedef *f) {
2006b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_inttable_count(&f->deps);
2007b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
2008b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2009b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_def *upb_filedef_def(const upb_filedef *f, size_t i) {
2010b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_value v;
2011b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2012b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upb_inttable_lookup32(&f->defs, i, &v)) {
2013b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return upb_value_getconstptr(v);
2014b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
2015b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return NULL;
2016b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
2017b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
2018b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2019b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_filedef *upb_filedef_dep(const upb_filedef *f, size_t i) {
2020b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_value v;
2021b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2022b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upb_inttable_lookup32(&f->deps, i, &v)) {
2023b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return upb_value_getconstptr(v);
2024b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
2025b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return NULL;
2026b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
2027b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
2028b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2029b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_filedef_setname(upb_filedef *f, const char *name, upb_status *s) {
2030b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  name = upb_gstrdup(name);
2031b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!name) {
2032b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_upberr_setoom(s);
2033b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
2034b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
2035b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_gfree((void*)f->name);
2036b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  f->name = name;
2037b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
2038b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
2039b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2040b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_filedef_setpackage(upb_filedef *f, const char *package,
2041b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                            upb_status *s) {
2042b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!upb_isident(package, strlen(package), true, s)) return false;
2043b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  package = upb_gstrdup(package);
2044b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!package) {
2045b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_upberr_setoom(s);
2046b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
2047b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
2048b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_gfree((void*)f->package);
2049b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  f->package = package;
2050b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
2051b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
2052b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2053b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_filedef_setsyntax(upb_filedef *f, upb_syntax_t syntax,
2054b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                           upb_status *s) {
2055b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(s);
2056b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (syntax != UPB_SYNTAX_PROTO2 &&
2057b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      syntax != UPB_SYNTAX_PROTO3) {
2058b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_status_seterrmsg(s, "Unknown syntax value.");
2059b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
2060b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
2061b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  f->syntax = syntax;
2062b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2063b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {
2064b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Set all messages in this file to match. */
2065b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    size_t i;
2066b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    for (i = 0; i < upb_filedef_defcount(f); i++) {
2067b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      /* Casting const away is safe since all defs in mutable filedef must
2068b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer       * also be mutable. */
2069b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_def *def = (upb_def*)upb_filedef_def(f, i);
2070b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2071b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_msgdef *m = upb_dyncast_msgdef_mutable(def);
2072b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (m) {
2073b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        m->syntax = syntax;
2074b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
2075b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
2076b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
2077b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2078b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
2079b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
2080b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2081b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_filedef_adddef(upb_filedef *f, upb_def *def, const void *ref_donor,
2082b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                        upb_status *s) {
2083b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (def->file) {
2084b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_status_seterrmsg(s, "Def is already part of another filedef.");
2085b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
2086b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
2087b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2088b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upb_inttable_push(&f->defs, upb_value_constptr(def))) {
2089b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    def->file = f;
2090b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_ref2(def, f);
2091b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (ref_donor) upb_def_unref(def, ref_donor);
2092b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (def->type == UPB_DEF_MSG) {
2093b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_downcast_msgdef_mutable(def)->syntax = f->syntax;
2094b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
2095b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return true;
2096b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
2097b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_upberr_setoom(s);
2098b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
2099b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
2100b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
2101b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2102b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_filedef_adddep(upb_filedef *f, const upb_filedef *dep) {
2103b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upb_inttable_push(&f->deps, upb_value_constptr(dep))) {
2104b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Regular ref instead of ref2 because files can't form cycles. */
2105b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_filedef_ref(dep, f);
2106b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return true;
2107b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
2108b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
2109b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
2110b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
2111b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/*
2112b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** TODO(haberman): it's unclear whether a lot of the consistency checks should
2113b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** assert() or return false.
2114b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer*/
2115b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2116b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2117b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <string.h>
2118b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2119b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2120b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void *upb_calloc(size_t size) {
2121b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  void *mem = upb_gmalloc(size);
2122b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (mem) {
2123b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    memset(mem, 0, size);
2124b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
2125b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return mem;
2126b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
2127b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2128b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Defined for the sole purpose of having a unique pointer value for
2129b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * UPB_NO_CLOSURE. */
2130b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerchar _upb_noclosure;
2131b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2132b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void freehandlers(upb_refcounted *r) {
2133b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_handlers *h = (upb_handlers*)r;
2134b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2135b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_iter i;
2136b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_begin(&i, &h->cleanup_);
2137b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
2138b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    void *val = (void*)upb_inttable_iter_key(&i);
2139b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_value func_val = upb_inttable_iter_value(&i);
2140b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_handlerfree *func = upb_value_getfptr(func_val);
2141b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    func(val);
2142b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
2143b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2144b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_uninit(&h->cleanup_);
2145b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_msgdef_unref(h->msg, h);
2146b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_gfree(h->sub);
2147b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_gfree(h);
2148b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
2149b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2150b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void visithandlers(const upb_refcounted *r, upb_refcounted_visit *visit,
2151b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                          void *closure) {
2152b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const upb_handlers *h = (const upb_handlers*)r;
2153b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_msg_field_iter i;
2154b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for(upb_msg_field_begin(&i, h->msg);
2155b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      !upb_msg_field_done(&i);
2156b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_msg_field_next(&i)) {
2157b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_fielddef *f = upb_msg_iter_field(&i);
2158b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    const upb_handlers *sub;
2159b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (!upb_fielddef_issubmsg(f)) continue;
2160b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    sub = upb_handlers_getsubhandlers(h, f);
2161b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (sub) visit(r, upb_handlers_upcast(sub), closure);
2162b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
2163b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
2164b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2165b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic const struct upb_refcounted_vtbl vtbl = {visithandlers, freehandlers};
2166b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2167b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammertypedef struct {
2168b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable tab;  /* maps upb_msgdef* -> upb_handlers*. */
2169b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_handlers_callback *callback;
2170b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const void *closure;
2171b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer} dfs_state;
2172b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2173b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* TODO(haberman): discard upb_handlers* objects that do not actually have any
2174b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * handlers set and cannot reach any upb_handlers* object that does.  This is
2175b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * slightly tricky to do correctly. */
2176b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic upb_handlers *newformsg(const upb_msgdef *m, const void *owner,
2177b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                               dfs_state *s) {
2178b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_msg_field_iter i;
2179b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_handlers *h = upb_handlers_new(m, owner);
2180b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!h) return NULL;
2181b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!upb_inttable_insertptr(&s->tab, m, upb_value_ptr(h))) goto oom;
2182b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2183b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  s->callback(s->closure, h);
2184b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2185b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* For each submessage field, get or create a handlers object and set it as
2186b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * the subhandlers. */
2187b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for(upb_msg_field_begin(&i, m);
2188b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      !upb_msg_field_done(&i);
2189b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_msg_field_next(&i)) {
2190b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_fielddef *f = upb_msg_iter_field(&i);
2191b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    const upb_msgdef *subdef;
2192b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_value subm_ent;
2193b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2194b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (!upb_fielddef_issubmsg(f)) continue;
2195b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2196b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    subdef = upb_downcast_msgdef(upb_fielddef_subdef(f));
2197b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (upb_inttable_lookupptr(&s->tab, subdef, &subm_ent)) {
2198b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_handlers_setsubhandlers(h, f, upb_value_getptr(subm_ent));
2199b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    } else {
2200b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_handlers *sub_mh = newformsg(subdef, &sub_mh, s);
2201b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (!sub_mh) goto oom;
2202b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_handlers_setsubhandlers(h, f, sub_mh);
2203b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_handlers_unref(sub_mh, &sub_mh);
2204b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
2205b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
2206b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return h;
2207b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2208b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammeroom:
2209b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_handlers_unref(h, owner);
2210b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return NULL;
2211b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
2212b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2213b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Given a selector for a STARTSUBMSG handler, resolves to a pointer to the
2214b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * subhandlers for this submessage field. */
2215b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#define SUBH(h, selector) (h->sub[selector])
2216b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2217b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* The selector for a submessage field is the field index. */
2218b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#define SUBH_F(h, f) SUBH(h, f->index_)
2219b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2220b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic int32_t trygetsel(upb_handlers *h, const upb_fielddef *f,
2221b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                         upb_handlertype_t type) {
2222b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_selector_t sel;
2223b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(!upb_handlers_isfrozen(h));
2224b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upb_handlers_msgdef(h) != upb_fielddef_containingtype(f)) {
2225b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_status_seterrf(
2226b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        &h->status_, "type mismatch: field %s does not belong to message %s",
2227b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_fielddef_name(f), upb_msgdef_fullname(upb_handlers_msgdef(h)));
2228b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return -1;
2229b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
2230b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!upb_handlers_getselector(f, type, &sel)) {
2231b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_status_seterrf(
2232b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        &h->status_,
2233b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        "type mismatch: cannot register handler type %d for field %s",
2234b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        type, upb_fielddef_name(f));
2235b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return -1;
2236b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
2237b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return sel;
2238b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
2239b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2240b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic upb_selector_t handlers_getsel(upb_handlers *h, const upb_fielddef *f,
2241b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                             upb_handlertype_t type) {
2242b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  int32_t sel = trygetsel(h, f, type);
2243b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(sel >= 0);
2244b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return sel;
2245b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
2246b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2247b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic const void **returntype(upb_handlers *h, const upb_fielddef *f,
2248b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                               upb_handlertype_t type) {
2249b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return &h->table[handlers_getsel(h, f, type)].attr.return_closure_type_;
2250b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
2251b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2252b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool doset(upb_handlers *h, int32_t sel, const upb_fielddef *f,
2253b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                  upb_handlertype_t type, upb_func *func,
2254b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                  upb_handlerattr *attr) {
2255b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_handlerattr set_attr = UPB_HANDLERATTR_INITIALIZER;
2256b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const void *closure_type;
2257b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const void **context_closure_type;
2258b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2259b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(!upb_handlers_isfrozen(h));
2260b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2261b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (sel < 0) {
2262b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_status_seterrmsg(&h->status_,
2263b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                         "incorrect handler type for this field.");
2264b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
2265b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
2266b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2267b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (h->table[sel].func) {
2268b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_status_seterrmsg(&h->status_,
2269b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                         "cannot change handler once it has been set.");
2270b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
2271b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
2272b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2273b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (attr) {
2274b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    set_attr = *attr;
2275b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
2276b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2277b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Check that the given closure type matches the closure type that has been
2278b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * established for this context (if any). */
2279b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  closure_type = upb_handlerattr_closuretype(&set_attr);
2280b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2281b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (type == UPB_HANDLER_STRING) {
2282b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    context_closure_type = returntype(h, f, UPB_HANDLER_STARTSTR);
2283b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else if (f && upb_fielddef_isseq(f) &&
2284b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer             type != UPB_HANDLER_STARTSEQ &&
2285b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer             type != UPB_HANDLER_ENDSEQ) {
2286b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    context_closure_type = returntype(h, f, UPB_HANDLER_STARTSEQ);
2287b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
2288b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    context_closure_type = &h->top_closure_type;
2289b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
2290b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2291b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (closure_type && *context_closure_type &&
2292b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      closure_type != *context_closure_type) {
2293b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* TODO(haberman): better message for debugging. */
2294b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (f) {
2295b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_status_seterrf(&h->status_,
2296b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                         "closure type does not match for field %s",
2297b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                         upb_fielddef_name(f));
2298b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    } else {
2299b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_status_seterrmsg(
2300b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          &h->status_, "closure type does not match for message-level handler");
2301b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
2302b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
2303b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
2304b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2305b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (closure_type)
2306b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    *context_closure_type = closure_type;
2307b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2308b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* If this is a STARTSEQ or STARTSTR handler, check that the returned pointer
2309b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * matches any pre-existing expectations about what type is expected. */
2310b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (type == UPB_HANDLER_STARTSEQ || type == UPB_HANDLER_STARTSTR) {
2311b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    const void *return_type = upb_handlerattr_returnclosuretype(&set_attr);
2312b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    const void *table_return_type =
2313b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_handlerattr_returnclosuretype(&h->table[sel].attr);
2314b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (return_type && table_return_type && return_type != table_return_type) {
2315b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_status_seterrmsg(&h->status_, "closure return type does not match");
2316b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return false;
2317b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
2318b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2319b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (table_return_type && !return_type)
2320b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_handlerattr_setreturnclosuretype(&set_attr, table_return_type);
2321b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
2322b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2323b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  h->table[sel].func = (upb_func*)func;
2324b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  h->table[sel].attr = set_attr;
2325b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
2326b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
2327b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2328b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Returns the effective closure type for this handler (which will propagate
2329b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * from outer frames if this frame has no START* handler).  Not implemented for
2330b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * UPB_HANDLER_STRING at the moment since this is not needed.  Returns NULL is
2331b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * the effective closure type is unspecified (either no handler was registered
2332b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * to specify it or the handler that was registered did not specify the closure
2333b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * type). */
2334b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst void *effective_closure_type(upb_handlers *h, const upb_fielddef *f,
2335b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                   upb_handlertype_t type) {
2336b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const void *ret;
2337b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_selector_t sel;
2338b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2339b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(type != UPB_HANDLER_STRING);
2340b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  ret = h->top_closure_type;
2341b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2342b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upb_fielddef_isseq(f) &&
2343b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      type != UPB_HANDLER_STARTSEQ &&
2344b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      type != UPB_HANDLER_ENDSEQ &&
2345b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      h->table[sel = handlers_getsel(h, f, UPB_HANDLER_STARTSEQ)].func) {
2346b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    ret = upb_handlerattr_returnclosuretype(&h->table[sel].attr);
2347b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
2348b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2349b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (type == UPB_HANDLER_STRING &&
2350b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      h->table[sel = handlers_getsel(h, f, UPB_HANDLER_STARTSTR)].func) {
2351b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    ret = upb_handlerattr_returnclosuretype(&h->table[sel].attr);
2352b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
2353b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2354b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* The effective type of the submessage; not used yet.
2355b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * if (type == SUBMESSAGE &&
2356b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   *     h->table[sel = handlers_getsel(h, f, UPB_HANDLER_STARTSUBMSG)].func) {
2357b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   *   ret = upb_handlerattr_returnclosuretype(&h->table[sel].attr);
2358b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * } */
2359b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2360b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return ret;
2361b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
2362b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2363b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Checks whether the START* handler specified by f & type is missing even
2364b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * though it is required to convert the established type of an outer frame
2365b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * ("closure_type") into the established type of an inner frame (represented in
2366b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * the return closure type of this handler's attr. */
2367b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool checkstart(upb_handlers *h, const upb_fielddef *f, upb_handlertype_t type,
2368b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                upb_status *status) {
2369b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const void *closure_type;
2370b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const upb_handlerattr *attr;
2371b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const void *return_closure_type;
2372b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2373b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_selector_t sel = handlers_getsel(h, f, type);
2374b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (h->table[sel].func) return true;
2375b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  closure_type = effective_closure_type(h, f, type);
2376b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  attr = &h->table[sel].attr;
2377b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return_closure_type = upb_handlerattr_returnclosuretype(attr);
2378b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (closure_type && return_closure_type &&
2379b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      closure_type != return_closure_type) {
2380b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_status_seterrf(status,
2381b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                       "expected start handler to return sub type for field %f",
2382b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                       upb_fielddef_name(f));
2383b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
2384b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
2385b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
2386b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
2387b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2388b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Public interface ***********************************************************/
2389b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2390b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerupb_handlers *upb_handlers_new(const upb_msgdef *md, const void *owner) {
2391b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  int extra;
2392b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_handlers *h;
2393b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2394b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(upb_msgdef_isfrozen(md));
2395b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2396b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  extra = sizeof(upb_handlers_tabent) * (md->selector_count - 1);
2397b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  h = upb_calloc(sizeof(*h) + extra);
2398b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!h) return NULL;
2399b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2400b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  h->msg = md;
2401b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_msgdef_ref(h->msg, h);
2402b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_status_clear(&h->status_);
2403b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2404b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (md->submsg_field_count > 0) {
2405b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    h->sub = upb_calloc(md->submsg_field_count * sizeof(*h->sub));
2406b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (!h->sub) goto oom;
2407b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
2408b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    h->sub = 0;
2409b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
2410b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2411b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!upb_refcounted_init(upb_handlers_upcast_mutable(h), &vtbl, owner))
2412b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    goto oom;
2413b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!upb_inttable_init(&h->cleanup_, UPB_CTYPE_FPTR)) goto oom;
2414b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2415b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* calloc() above initialized all handlers to NULL. */
2416b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return h;
2417b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2418b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammeroom:
2419b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  freehandlers(upb_handlers_upcast_mutable(h));
2420b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return NULL;
2421b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
2422b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2423b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_handlers *upb_handlers_newfrozen(const upb_msgdef *m,
2424b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                           const void *owner,
2425b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                           upb_handlers_callback *callback,
2426b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                           const void *closure) {
2427b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  dfs_state state;
2428b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_handlers *ret;
2429b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bool ok;
2430b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_refcounted *r;
2431b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2432b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  state.callback = callback;
2433b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  state.closure = closure;
2434b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!upb_inttable_init(&state.tab, UPB_CTYPE_PTR)) return NULL;
2435b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2436b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  ret = newformsg(m, owner, &state);
2437b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2438b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_uninit(&state.tab);
2439b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!ret) return NULL;
2440b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2441b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  r = upb_handlers_upcast_mutable(ret);
2442b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  ok = upb_refcounted_freeze(&r, 1, NULL, UPB_MAX_HANDLER_DEPTH);
2443b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_ASSERT_VAR(ok, ok);
2444b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2445b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return ret;
2446b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
2447b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2448b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_status *upb_handlers_status(upb_handlers *h) {
2449b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(!upb_handlers_isfrozen(h));
2450b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return &h->status_;
2451b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
2452b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2453b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_handlers_clearerr(upb_handlers *h) {
2454b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(!upb_handlers_isfrozen(h));
2455b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_status_clear(&h->status_);
2456b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
2457b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2458b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#define SETTER(name, handlerctype, handlertype) \
2459b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bool upb_handlers_set ## name(upb_handlers *h, const upb_fielddef *f, \
2460b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                handlerctype func, upb_handlerattr *attr) { \
2461b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    int32_t sel = trygetsel(h, f, handlertype); \
2462b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return doset(h, sel, f, handlertype, (upb_func*)func, attr); \
2463b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
2464b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2465b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerSETTER(int32,       upb_int32_handlerfunc*,       UPB_HANDLER_INT32)
2466b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerSETTER(int64,       upb_int64_handlerfunc*,       UPB_HANDLER_INT64)
2467b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerSETTER(uint32,      upb_uint32_handlerfunc*,      UPB_HANDLER_UINT32)
2468b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerSETTER(uint64,      upb_uint64_handlerfunc*,      UPB_HANDLER_UINT64)
2469b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerSETTER(float,       upb_float_handlerfunc*,       UPB_HANDLER_FLOAT)
2470b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerSETTER(double,      upb_double_handlerfunc*,      UPB_HANDLER_DOUBLE)
2471b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerSETTER(bool,        upb_bool_handlerfunc*,        UPB_HANDLER_BOOL)
2472b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerSETTER(startstr,    upb_startstr_handlerfunc*,    UPB_HANDLER_STARTSTR)
2473b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerSETTER(string,      upb_string_handlerfunc*,      UPB_HANDLER_STRING)
2474b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerSETTER(endstr,      upb_endfield_handlerfunc*,    UPB_HANDLER_ENDSTR)
2475b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerSETTER(startseq,    upb_startfield_handlerfunc*,  UPB_HANDLER_STARTSEQ)
2476b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerSETTER(startsubmsg, upb_startfield_handlerfunc*,  UPB_HANDLER_STARTSUBMSG)
2477b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerSETTER(endsubmsg,   upb_endfield_handlerfunc*,    UPB_HANDLER_ENDSUBMSG)
2478b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerSETTER(endseq,      upb_endfield_handlerfunc*,    UPB_HANDLER_ENDSEQ)
2479b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2480b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#undef SETTER
2481b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2482b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_handlers_setstartmsg(upb_handlers *h, upb_startmsg_handlerfunc *func,
2483b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                              upb_handlerattr *attr) {
2484b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return doset(h, UPB_STARTMSG_SELECTOR, NULL, UPB_HANDLER_INT32,
2485b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer               (upb_func *)func, attr);
2486b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
2487b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2488b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_handlers_setendmsg(upb_handlers *h, upb_endmsg_handlerfunc *func,
2489b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                            upb_handlerattr *attr) {
2490b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(!upb_handlers_isfrozen(h));
2491b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return doset(h, UPB_ENDMSG_SELECTOR, NULL, UPB_HANDLER_INT32,
2492b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer               (upb_func *)func, attr);
2493b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
2494b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2495b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_handlers_setsubhandlers(upb_handlers *h, const upb_fielddef *f,
2496b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                 const upb_handlers *sub) {
2497b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(sub);
2498b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(!upb_handlers_isfrozen(h));
2499b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(upb_fielddef_issubmsg(f));
2500b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (SUBH_F(h, f)) return false;  /* Can't reset. */
2501b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upb_msgdef_upcast(upb_handlers_msgdef(sub)) != upb_fielddef_subdef(f)) {
2502b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
2503b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
2504b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  SUBH_F(h, f) = sub;
2505b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_ref2(sub, h);
2506b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
2507b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
2508b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2509b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_handlers *upb_handlers_getsubhandlers(const upb_handlers *h,
2510b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                                const upb_fielddef *f) {
2511b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(upb_fielddef_issubmsg(f));
2512b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return SUBH_F(h, f);
2513b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
2514b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2515b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_handlers_getattr(const upb_handlers *h, upb_selector_t sel,
2516b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                          upb_handlerattr *attr) {
2517b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!upb_handlers_gethandler(h, sel))
2518b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
2519b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  *attr = h->table[sel].attr;
2520b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
2521b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
2522b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2523b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_handlers *upb_handlers_getsubhandlers_sel(const upb_handlers *h,
2524b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                                    upb_selector_t sel) {
2525b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* STARTSUBMSG selector in sel is the field's selector base. */
2526b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return SUBH(h, sel - UPB_STATIC_SELECTOR_COUNT);
2527b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
2528b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2529b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_msgdef *upb_handlers_msgdef(const upb_handlers *h) { return h->msg; }
2530b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2531b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_handlers_addcleanup(upb_handlers *h, void *p, upb_handlerfree *func) {
2532b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bool ok;
2533b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upb_inttable_lookupptr(&h->cleanup_, p, NULL)) {
2534b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
2535b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
2536b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  ok = upb_inttable_insertptr(&h->cleanup_, p, upb_value_fptr(func));
2537b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_ASSERT_VAR(ok, ok);
2538b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
2539b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
2540b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2541b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2542b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* "Static" methods ***********************************************************/
2543b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2544b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_handlers_freeze(upb_handlers *const*handlers, int n, upb_status *s) {
2545b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* TODO: verify we have a transitive closure. */
2546b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  int i;
2547b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for (i = 0; i < n; i++) {
2548b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_msg_field_iter j;
2549b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_handlers *h = handlers[i];
2550b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2551b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (!upb_ok(&h->status_)) {
2552b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_status_seterrf(s, "handlers for message %s had error status: %s",
2553b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                         upb_msgdef_fullname(upb_handlers_msgdef(h)),
2554b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                         upb_status_errmsg(&h->status_));
2555b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return false;
2556b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
2557b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2558b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Check that there are no closure mismatches due to missing Start* handlers
2559b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * or subhandlers with different type-level types. */
2560b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    for(upb_msg_field_begin(&j, h->msg);
2561b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        !upb_msg_field_done(&j);
2562b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_msg_field_next(&j)) {
2563b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2564b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      const upb_fielddef *f = upb_msg_iter_field(&j);
2565b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (upb_fielddef_isseq(f)) {
2566b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        if (!checkstart(h, f, UPB_HANDLER_STARTSEQ, s))
2567b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          return false;
2568b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
2569b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2570b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (upb_fielddef_isstring(f)) {
2571b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        if (!checkstart(h, f, UPB_HANDLER_STARTSTR, s))
2572b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          return false;
2573b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
2574b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2575b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (upb_fielddef_issubmsg(f)) {
2576b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        bool hashandler = false;
2577b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        if (upb_handlers_gethandler(
2578b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                h, handlers_getsel(h, f, UPB_HANDLER_STARTSUBMSG)) ||
2579b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer            upb_handlers_gethandler(
2580b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                h, handlers_getsel(h, f, UPB_HANDLER_ENDSUBMSG))) {
2581b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          hashandler = true;
2582b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        }
2583b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2584b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        if (upb_fielddef_isseq(f) &&
2585b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer            (upb_handlers_gethandler(
2586b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                 h, handlers_getsel(h, f, UPB_HANDLER_STARTSEQ)) ||
2587b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer             upb_handlers_gethandler(
2588b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                 h, handlers_getsel(h, f, UPB_HANDLER_ENDSEQ)))) {
2589b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          hashandler = true;
2590b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        }
2591b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2592b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        if (hashandler && !upb_handlers_getsubhandlers(h, f)) {
2593b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          /* For now we add an empty subhandlers in this case.  It makes the
2594b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer           * decoder code generator simpler, because it only has to handle two
2595b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer           * cases (submessage has handlers or not) as opposed to three
2596b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer           * (submessage has handlers in enclosing message but no subhandlers).
2597b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer           *
2598b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer           * This makes parsing less efficient in the case that we want to
2599b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer           * notice a submessage but skip its contents (like if we're testing
2600b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer           * for submessage presence or counting the number of repeated
2601b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer           * submessages).  In this case we will end up parsing the submessage
2602b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer           * field by field and throwing away the results for each, instead of
2603b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer           * skipping the whole delimited thing at once.  If this is an issue we
2604b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer           * can revisit it, but do remember that this only arises when you have
2605b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer           * handlers (startseq/startsubmsg/endsubmsg/endseq) set for the
2606b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer           * submessage but no subhandlers.  The uses cases for this are
2607b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer           * limited. */
2608b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          upb_handlers *sub = upb_handlers_new(upb_fielddef_msgsubdef(f), &sub);
2609b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          upb_handlers_setsubhandlers(h, f, sub);
2610b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          upb_handlers_unref(sub, &sub);
2611b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        }
2612b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2613b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        /* TODO(haberman): check type of submessage.
2614b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer         * This is slightly tricky; also consider whether we should check that
2615b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer         * they match at setsubhandlers time. */
2616b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
2617b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
2618b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
2619b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2620b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!upb_refcounted_freeze((upb_refcounted*const*)handlers, n, s,
2621b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                             UPB_MAX_HANDLER_DEPTH)) {
2622b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
2623b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
2624b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2625b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
2626b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
2627b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2628b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerupb_handlertype_t upb_handlers_getprimitivehandlertype(const upb_fielddef *f) {
2629b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  switch (upb_fielddef_type(f)) {
2630b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_INT32:
2631b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_ENUM: return UPB_HANDLER_INT32;
2632b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_INT64: return UPB_HANDLER_INT64;
2633b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_UINT32: return UPB_HANDLER_UINT32;
2634b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_UINT64: return UPB_HANDLER_UINT64;
2635b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_FLOAT: return UPB_HANDLER_FLOAT;
2636b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_DOUBLE: return UPB_HANDLER_DOUBLE;
2637b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_BOOL: return UPB_HANDLER_BOOL;
2638b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    default: assert(false); return -1;  /* Invalid input. */
2639b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
2640b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
2641b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2642b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_handlers_getselector(const upb_fielddef *f, upb_handlertype_t type,
2643b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                              upb_selector_t *s) {
2644b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  switch (type) {
2645b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_HANDLER_INT32:
2646b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_HANDLER_INT64:
2647b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_HANDLER_UINT32:
2648b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_HANDLER_UINT64:
2649b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_HANDLER_FLOAT:
2650b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_HANDLER_DOUBLE:
2651b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_HANDLER_BOOL:
2652b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (!upb_fielddef_isprimitive(f) ||
2653b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          upb_handlers_getprimitivehandlertype(f) != type)
2654b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        return false;
2655b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      *s = f->selector_base;
2656b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
2657b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_HANDLER_STRING:
2658b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (upb_fielddef_isstring(f)) {
2659b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        *s = f->selector_base;
2660b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      } else if (upb_fielddef_lazy(f)) {
2661b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        *s = f->selector_base + 3;
2662b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      } else {
2663b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        return false;
2664b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
2665b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
2666b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_HANDLER_STARTSTR:
2667b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (upb_fielddef_isstring(f) || upb_fielddef_lazy(f)) {
2668b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        *s = f->selector_base + 1;
2669b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      } else {
2670b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        return false;
2671b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
2672b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
2673b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_HANDLER_ENDSTR:
2674b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (upb_fielddef_isstring(f) || upb_fielddef_lazy(f)) {
2675b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        *s = f->selector_base + 2;
2676b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      } else {
2677b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        return false;
2678b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
2679b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
2680b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_HANDLER_STARTSEQ:
2681b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (!upb_fielddef_isseq(f)) return false;
2682b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      *s = f->selector_base - 2;
2683b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
2684b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_HANDLER_ENDSEQ:
2685b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (!upb_fielddef_isseq(f)) return false;
2686b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      *s = f->selector_base - 1;
2687b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
2688b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_HANDLER_STARTSUBMSG:
2689b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (!upb_fielddef_issubmsg(f)) return false;
2690b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      /* Selectors for STARTSUBMSG are at the beginning of the table so that the
2691b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer       * selector can also be used as an index into the "sub" array of
2692b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer       * subhandlers.  The indexes for the two into these two tables are the
2693b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer       * same, except that in the handler table the static selectors come first. */
2694b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      *s = f->index_ + UPB_STATIC_SELECTOR_COUNT;
2695b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
2696b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_HANDLER_ENDSUBMSG:
2697b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (!upb_fielddef_issubmsg(f)) return false;
2698b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      *s = f->selector_base;
2699b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
2700b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
2701b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert((size_t)*s < upb_fielddef_containingtype(f)->selector_count);
2702b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
2703b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
2704b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2705b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammeruint32_t upb_handlers_selectorbaseoffset(const upb_fielddef *f) {
2706b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_fielddef_isseq(f) ? 2 : 0;
2707b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
2708b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2709b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammeruint32_t upb_handlers_selectorcount(const upb_fielddef *f) {
2710b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  uint32_t ret = 1;
2711b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upb_fielddef_isseq(f)) ret += 2;    /* STARTSEQ/ENDSEQ */
2712b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upb_fielddef_isstring(f)) ret += 2; /* [STRING]/STARTSTR/ENDSTR */
2713b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upb_fielddef_issubmsg(f)) {
2714b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* ENDSUBMSG (STARTSUBMSG is at table beginning) */
2715b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    ret += 0;
2716b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (upb_fielddef_lazy(f)) {
2717b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      /* STARTSTR/ENDSTR/STRING (for lazy) */
2718b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      ret += 3;
2719b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
2720b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
2721b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return ret;
2722b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
2723b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2724b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2725b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* upb_handlerattr ************************************************************/
2726b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2727b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_handlerattr_init(upb_handlerattr *attr) {
2728b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_handlerattr from = UPB_HANDLERATTR_INITIALIZER;
2729b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  memcpy(attr, &from, sizeof(*attr));
2730b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
2731b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2732b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_handlerattr_uninit(upb_handlerattr *attr) {
2733b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(attr);
2734b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
2735b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2736b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_handlerattr_sethandlerdata(upb_handlerattr *attr, const void *hd) {
2737b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  attr->handler_data_ = hd;
2738b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
2739b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
2740b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2741b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_handlerattr_setclosuretype(upb_handlerattr *attr, const void *type) {
2742b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  attr->closure_type_ = type;
2743b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
2744b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
2745b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2746b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst void *upb_handlerattr_closuretype(const upb_handlerattr *attr) {
2747b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return attr->closure_type_;
2748b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
2749b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2750b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_handlerattr_setreturnclosuretype(upb_handlerattr *attr,
2751b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                          const void *type) {
2752b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  attr->return_closure_type_ = type;
2753b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
2754b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
2755b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2756b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst void *upb_handlerattr_returnclosuretype(const upb_handlerattr *attr) {
2757b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return attr->return_closure_type_;
2758b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
2759b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2760b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_handlerattr_setalwaysok(upb_handlerattr *attr, bool alwaysok) {
2761b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  attr->alwaysok_ = alwaysok;
2762b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
2763b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
2764b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2765b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_handlerattr_alwaysok(const upb_handlerattr *attr) {
2766b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return attr->alwaysok_;
2767b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
2768b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2769b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* upb_bufhandle **************************************************************/
2770b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2771b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammersize_t upb_bufhandle_objofs(const upb_bufhandle *h) {
2772b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return h->objofs_;
2773b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
2774b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2775b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* upb_byteshandler ***********************************************************/
2776b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2777b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_byteshandler_init(upb_byteshandler* h) {
2778b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  memset(h, 0, sizeof(*h));
2779b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
2780b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2781b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* For when we support handlerfree callbacks. */
2782b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_byteshandler_uninit(upb_byteshandler* h) {
2783b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(h);
2784b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
2785b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2786b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_byteshandler_setstartstr(upb_byteshandler *h,
2787b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                  upb_startstr_handlerfunc *func, void *d) {
2788b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  h->table[UPB_STARTSTR_SELECTOR].func = (upb_func*)func;
2789b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  h->table[UPB_STARTSTR_SELECTOR].attr.handler_data_ = d;
2790b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
2791b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
2792b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2793b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_byteshandler_setstring(upb_byteshandler *h,
2794b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                upb_string_handlerfunc *func, void *d) {
2795b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  h->table[UPB_STRING_SELECTOR].func = (upb_func*)func;
2796b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  h->table[UPB_STRING_SELECTOR].attr.handler_data_ = d;
2797b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
2798b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
2799b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2800b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_byteshandler_setendstr(upb_byteshandler *h,
2801b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                upb_endfield_handlerfunc *func, void *d) {
2802b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  h->table[UPB_ENDSTR_SELECTOR].func = (upb_func*)func;
2803b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  h->table[UPB_ENDSTR_SELECTOR].attr.handler_data_ = d;
2804b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
2805b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
2806b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/*
2807b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** upb::RefCounted Implementation
2808b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer**
2809b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** Our key invariants are:
2810b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** 1. reference cycles never span groups
2811b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** 2. for ref2(to, from), we increment to's count iff group(from) != group(to)
2812b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer**
2813b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** The previous two are how we avoid leaking cycles.  Other important
2814b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** invariants are:
2815b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** 3. for mutable objects "from" and "to", if there exists a ref2(to, from)
2816b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer**    this implies group(from) == group(to).  (In practice, what we implement
2817b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer**    is even stronger; "from" and "to" will share a group if there has *ever*
2818b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer**    been a ref2(to, from), but all that is necessary for correctness is the
2819b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer**    weaker one).
2820b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** 4. mutable and immutable objects are never in the same group.
2821b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer*/
2822b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2823b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2824b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <setjmp.h>
2825b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2826b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void freeobj(upb_refcounted *o);
2827b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2828b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst char untracked_val;
2829b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst void *UPB_UNTRACKED_REF = &untracked_val;
2830b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2831b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* arch-specific atomic primitives  *******************************************/
2832b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2833b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#ifdef UPB_THREAD_UNSAFE /*---------------------------------------------------*/
2834b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2835b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void atomic_inc(uint32_t *a) { (*a)++; }
2836b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool atomic_dec(uint32_t *a) { return --(*a) == 0; }
2837b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2838b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#elif defined(__GNUC__) || defined(__clang__) /*------------------------------*/
2839b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2840b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void atomic_inc(uint32_t *a) { __sync_fetch_and_add(a, 1); }
2841b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool atomic_dec(uint32_t *a) { return __sync_sub_and_fetch(a, 1) == 0; }
2842b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2843b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#elif defined(WIN32) /*-------------------------------------------------------*/
2844b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2845b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <Windows.h>
2846b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2847b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void atomic_inc(upb_atomic_t *a) { InterlockedIncrement(&a->val); }
2848b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool atomic_dec(upb_atomic_t *a) {
2849b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return InterlockedDecrement(&a->val) == 0;
2850b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
2851b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2852b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#else
2853b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#error Atomic primitives not defined for your platform/CPU.  \
2854b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer       Implement them or compile with UPB_THREAD_UNSAFE.
2855b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#endif
2856b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2857b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* All static objects point to this refcount.
2858b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * It is special-cased in ref/unref below.  */
2859b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammeruint32_t static_refcount = -1;
2860b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2861b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* We can avoid atomic ops for statically-declared objects.
2862b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * This is a minor optimization but nice since we can avoid degrading under
2863b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * contention in this case. */
2864b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2865b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void refgroup(uint32_t *group) {
2866b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (group != &static_refcount)
2867b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    atomic_inc(group);
2868b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
2869b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2870b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool unrefgroup(uint32_t *group) {
2871b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (group == &static_refcount) {
2872b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
2873b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
2874b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return atomic_dec(group);
2875b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
2876b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
2877b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2878b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2879b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Reference tracking (debug only) ********************************************/
2880b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2881b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#ifdef UPB_DEBUG_REFS
2882b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2883b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#ifdef UPB_THREAD_UNSAFE
2884b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2885b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void upb_lock() {}
2886b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void upb_unlock() {}
2887b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2888b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#else
2889b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2890b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* User must define functions that lock/unlock a global mutex and link this
2891b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * file against them. */
2892b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_lock();
2893b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_unlock();
2894b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2895b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#endif
2896b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2897b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* UPB_DEBUG_REFS mode counts on being able to malloc() memory in some
2898b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * code-paths that can normally never fail, like upb_refcounted_ref().  Since
2899b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * we have no way to propagage out-of-memory errors back to the user, and since
2900b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * these errors can only occur in UPB_DEBUG_REFS mode, we use an allocator that
2901b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * immediately aborts on failure (avoiding the global allocator, which might
2902b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * inject failures). */
2903b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2904b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <stdlib.h>
2905b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2906b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void *upb_debugrefs_allocfunc(upb_alloc *alloc, void *ptr,
2907b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                     size_t oldsize, size_t size) {
2908b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(alloc);
2909b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(oldsize);
2910b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (size == 0) {
2911b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    free(ptr);
2912b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return NULL;
2913b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
2914b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    void *ret = realloc(ptr, size);
2915b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2916b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (!ret) {
2917b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      abort();
2918b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
2919b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2920b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return ret;
2921b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
2922b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
2923b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2924b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerupb_alloc upb_alloc_debugrefs = {&upb_debugrefs_allocfunc};
2925b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2926b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammertypedef struct {
2927b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  int count;  /* How many refs there are (duplicates only allowed for ref2). */
2928b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bool is_ref2;
2929b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer} trackedref;
2930b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2931b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic trackedref *trackedref_new(bool is_ref2) {
2932b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  trackedref *ret = upb_malloc(&upb_alloc_debugrefs, sizeof(*ret));
2933b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  ret->count = 1;
2934b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  ret->is_ref2 = is_ref2;
2935b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return ret;
2936b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
2937b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2938b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void track(const upb_refcounted *r, const void *owner, bool ref2) {
2939b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_value v;
2940b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2941b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(owner);
2942b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (owner == UPB_UNTRACKED_REF) return;
2943b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2944b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_lock();
2945b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upb_inttable_lookupptr(r->refs, owner, &v)) {
2946b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    trackedref *ref = upb_value_getptr(v);
2947b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Since we allow multiple ref2's for the same to/from pair without
2948b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * allocating separate memory for each one, we lose the fine-grained
2949b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * tracking behavior we get with regular refs.  Since ref2s only happen
2950b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * inside upb, we'll accept this limitation until/unless there is a really
2951b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * difficult upb-internal bug that can't be figured out without it. */
2952b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    assert(ref2);
2953b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    assert(ref->is_ref2);
2954b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    ref->count++;
2955b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
2956b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    trackedref *ref = trackedref_new(ref2);
2957b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_inttable_insertptr2(r->refs, owner, upb_value_ptr(ref),
2958b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                            &upb_alloc_debugrefs);
2959b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (ref2) {
2960b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      /* We know this cast is safe when it is a ref2, because it's coming from
2961b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer       * another refcounted object. */
2962b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      const upb_refcounted *from = owner;
2963b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      assert(!upb_inttable_lookupptr(from->ref2s, r, NULL));
2964b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_inttable_insertptr2(from->ref2s, r, upb_value_ptr(NULL),
2965b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                              &upb_alloc_debugrefs);
2966b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
2967b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
2968b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_unlock();
2969b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
2970b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2971b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void untrack(const upb_refcounted *r, const void *owner, bool ref2) {
2972b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_value v;
2973b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bool found;
2974b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  trackedref *ref;
2975b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2976b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(owner);
2977b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (owner == UPB_UNTRACKED_REF) return;
2978b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2979b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_lock();
2980b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  found = upb_inttable_lookupptr(r->refs, owner, &v);
2981b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* This assert will fail if an owner attempts to release a ref it didn't have. */
2982b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_ASSERT_VAR(found, found);
2983b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  ref = upb_value_getptr(v);
2984b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(ref->is_ref2 == ref2);
2985b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (--ref->count == 0) {
2986b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    free(ref);
2987b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_inttable_removeptr(r->refs, owner, NULL);
2988b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (ref2) {
2989b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      /* We know this cast is safe when it is a ref2, because it's coming from
2990b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer       * another refcounted object. */
2991b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      const upb_refcounted *from = owner;
2992b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      bool removed = upb_inttable_removeptr(from->ref2s, r, NULL);
2993b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      assert(removed);
2994b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
2995b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
2996b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_unlock();
2997b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
2998b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
2999b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void checkref(const upb_refcounted *r, const void *owner, bool ref2) {
3000b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_value v;
3001b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bool found;
3002b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  trackedref *ref;
3003b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3004b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_lock();
3005b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  found = upb_inttable_lookupptr(r->refs, owner, &v);
3006b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_ASSERT_VAR(found, found);
3007b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  ref = upb_value_getptr(v);
3008b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(ref->is_ref2 == ref2);
3009b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_unlock();
3010b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
3011b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3012b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Populates the given UPB_CTYPE_INT32 inttable with counts of ref2's that
3013b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * originate from the given owner. */
3014b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void getref2s(const upb_refcounted *owner, upb_inttable *tab) {
3015b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_iter i;
3016b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3017b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_lock();
3018b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_begin(&i, owner->ref2s);
3019b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
3020b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_value v;
3021b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_value count;
3022b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    trackedref *ref;
3023b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    bool found;
3024b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3025b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_refcounted *to = (upb_refcounted*)upb_inttable_iter_key(&i);
3026b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3027b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* To get the count we need to look in the target's table. */
3028b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    found = upb_inttable_lookupptr(to->refs, owner, &v);
3029b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    assert(found);
3030b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    ref = upb_value_getptr(v);
3031b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    count = upb_value_int32(ref->count);
3032b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3033b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_inttable_insertptr2(tab, to, count, &upb_alloc_debugrefs);
3034b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
3035b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_unlock();
3036b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
3037b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3038b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammertypedef struct {
3039b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable ref2;
3040b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const upb_refcounted *obj;
3041b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer} check_state;
3042b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3043b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void visit_check(const upb_refcounted *obj, const upb_refcounted *subobj,
3044b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                        void *closure) {
3045b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  check_state *s = closure;
3046b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable *ref2 = &s->ref2;
3047b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_value v;
3048b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bool removed;
3049b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  int32_t newcount;
3050b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3051b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(obj == s->obj);
3052b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(subobj);
3053b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  removed = upb_inttable_removeptr(ref2, subobj, &v);
3054b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* The following assertion will fail if the visit() function visits a subobj
3055b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * that it did not have a ref2 on, or visits the same subobj too many times. */
3056b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(removed);
3057b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  newcount = upb_value_getint32(v) - 1;
3058b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (newcount > 0) {
3059b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_inttable_insert2(ref2, (uintptr_t)subobj, upb_value_int32(newcount),
3060b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                         &upb_alloc_debugrefs);
3061b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
3062b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
3063b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3064b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void visit(const upb_refcounted *r, upb_refcounted_visit *v,
3065b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                  void *closure) {
3066b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* In DEBUG_REFS mode we know what existing ref2 refs there are, so we know
3067b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * exactly the set of nodes that visit() should visit.  So we verify visit()'s
3068b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * correctness here. */
3069b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  check_state state;
3070b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  state.obj = r;
3071b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_init2(&state.ref2, UPB_CTYPE_INT32, &upb_alloc_debugrefs);
3072b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  getref2s(r, &state.ref2);
3073b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3074b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* This should visit any children in the ref2 table. */
3075b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (r->vtbl->visit) r->vtbl->visit(r, visit_check, &state);
3076b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3077b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* This assertion will fail if the visit() function missed any children. */
3078b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(upb_inttable_count(&state.ref2) == 0);
3079b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_uninit2(&state.ref2, &upb_alloc_debugrefs);
3080b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (r->vtbl->visit) r->vtbl->visit(r, v, closure);
3081b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
3082b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3083b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void trackinit(upb_refcounted *r) {
3084b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  r->refs = upb_malloc(&upb_alloc_debugrefs, sizeof(*r->refs));
3085b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  r->ref2s = upb_malloc(&upb_alloc_debugrefs, sizeof(*r->ref2s));
3086b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_init2(r->refs, UPB_CTYPE_PTR, &upb_alloc_debugrefs);
3087b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_init2(r->ref2s, UPB_CTYPE_PTR, &upb_alloc_debugrefs);
3088b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
3089b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3090b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void trackfree(const upb_refcounted *r) {
3091b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_uninit2(r->refs, &upb_alloc_debugrefs);
3092b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_uninit2(r->ref2s, &upb_alloc_debugrefs);
3093b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_free(&upb_alloc_debugrefs, r->refs);
3094b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_free(&upb_alloc_debugrefs, r->ref2s);
3095b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
3096b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3097b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#else
3098b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3099b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void track(const upb_refcounted *r, const void *owner, bool ref2) {
3100b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(r);
3101b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(owner);
3102b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(ref2);
3103b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
3104b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3105b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void untrack(const upb_refcounted *r, const void *owner, bool ref2) {
3106b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(r);
3107b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(owner);
3108b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(ref2);
3109b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
3110b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3111b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void checkref(const upb_refcounted *r, const void *owner, bool ref2) {
3112b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(r);
3113b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(owner);
3114b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(ref2);
3115b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
3116b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3117b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void trackinit(upb_refcounted *r) {
3118b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(r);
3119b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
3120b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3121b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void trackfree(const upb_refcounted *r) {
3122b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(r);
3123b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
3124b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3125b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void visit(const upb_refcounted *r, upb_refcounted_visit *v,
3126b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                  void *closure) {
3127b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (r->vtbl->visit) r->vtbl->visit(r, v, closure);
3128b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
3129b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3130b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#endif  /* UPB_DEBUG_REFS */
3131b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3132b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3133b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* freeze() *******************************************************************/
3134b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3135b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* The freeze() operation is by far the most complicated part of this scheme.
3136b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * We compute strongly-connected components and then mutate the graph such that
3137b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * we preserve the invariants documented at the top of this file.  And we must
3138b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * handle out-of-memory errors gracefully (without leaving the graph
3139b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * inconsistent), which adds to the fun. */
3140b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3141b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* The state used by the freeze operation (shared across many functions). */
3142b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammertypedef struct {
3143b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  int depth;
3144b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  int maxdepth;
3145b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  uint64_t index;
3146b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Maps upb_refcounted* -> attributes (color, etc).  attr layout varies by
3147b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * color. */
3148b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable objattr;
3149b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable stack;   /* stack of upb_refcounted* for Tarjan's algorithm. */
3150b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable groups;  /* array of uint32_t*, malloc'd refcounts for new groups */
3151b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_status *status;
3152b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  jmp_buf err;
3153b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer} tarjan;
3154b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3155b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void release_ref2(const upb_refcounted *obj,
3156b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                         const upb_refcounted *subobj,
3157b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                         void *closure);
3158b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3159b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Node attributes -----------------------------------------------------------*/
3160b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3161b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* After our analysis phase all nodes will be either GRAY or WHITE. */
3162b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3163b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammertypedef enum {
3164b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  BLACK = 0,  /* Object has not been seen. */
3165b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  GRAY,   /* Object has been found via a refgroup but may not be reachable. */
3166b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  GREEN,  /* Object is reachable and is currently on the Tarjan stack. */
3167b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  WHITE   /* Object is reachable and has been assigned a group (SCC). */
3168b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer} color_t;
3169b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3170b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerUPB_NORETURN static void err(tarjan *t) { longjmp(t->err, 1); }
3171b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerUPB_NORETURN static void oom(tarjan *t) {
3172b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_status_seterrmsg(t->status, "out of memory");
3173b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  err(t);
3174b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
3175b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3176b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic uint64_t trygetattr(const tarjan *t, const upb_refcounted *r) {
3177b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_value v;
3178b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_inttable_lookupptr(&t->objattr, r, &v) ?
3179b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_value_getuint64(v) : 0;
3180b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
3181b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3182b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic uint64_t getattr(const tarjan *t, const upb_refcounted *r) {
3183b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_value v;
3184b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bool found = upb_inttable_lookupptr(&t->objattr, r, &v);
3185b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_ASSERT_VAR(found, found);
3186b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_value_getuint64(v);
3187b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
3188b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3189b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void setattr(tarjan *t, const upb_refcounted *r, uint64_t attr) {
3190b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_removeptr(&t->objattr, r, NULL);
3191b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_insertptr(&t->objattr, r, upb_value_uint64(attr));
3192b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
3193b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3194b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic color_t color(tarjan *t, const upb_refcounted *r) {
3195b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return trygetattr(t, r) & 0x3;  /* Color is always stored in the low 2 bits. */
3196b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
3197b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3198b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void set_gray(tarjan *t, const upb_refcounted *r) {
3199b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(color(t, r) == BLACK);
3200b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  setattr(t, r, GRAY);
3201b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
3202b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3203b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Pushes an obj onto the Tarjan stack and sets it to GREEN. */
3204b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void push(tarjan *t, const upb_refcounted *r) {
3205b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(color(t, r) == BLACK || color(t, r) == GRAY);
3206b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* This defines the attr layout for the GREEN state.  "index" and "lowlink"
3207b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * get 31 bits, which is plenty (limit of 2B objects frozen at a time). */
3208b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  setattr(t, r, GREEN | (t->index << 2) | (t->index << 33));
3209b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (++t->index == 0x80000000) {
3210b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_status_seterrmsg(t->status, "too many objects to freeze");
3211b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    err(t);
3212b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
3213b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_push(&t->stack, upb_value_ptr((void*)r));
3214b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
3215b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3216b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Pops an obj from the Tarjan stack and sets it to WHITE, with a ptr to its
3217b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * SCC group. */
3218b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic upb_refcounted *pop(tarjan *t) {
3219b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_refcounted *r = upb_value_getptr(upb_inttable_pop(&t->stack));
3220b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(color(t, r) == GREEN);
3221b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* This defines the attr layout for nodes in the WHITE state.
3222b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * Top of group stack is [group, NULL]; we point at group. */
3223b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  setattr(t, r, WHITE | (upb_inttable_count(&t->groups) - 2) << 8);
3224b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return r;
3225b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
3226b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3227b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void tarjan_newgroup(tarjan *t) {
3228b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  uint32_t *group = upb_gmalloc(sizeof(*group));
3229b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!group) oom(t);
3230b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Push group and empty group leader (we'll fill in leader later). */
3231b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!upb_inttable_push(&t->groups, upb_value_ptr(group)) ||
3232b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      !upb_inttable_push(&t->groups, upb_value_ptr(NULL))) {
3233b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_gfree(group);
3234b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    oom(t);
3235b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
3236b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  *group = 0;
3237b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
3238b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3239b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic uint32_t idx(tarjan *t, const upb_refcounted *r) {
3240b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(color(t, r) == GREEN);
3241b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return (getattr(t, r) >> 2) & 0x7FFFFFFF;
3242b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
3243b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3244b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic uint32_t lowlink(tarjan *t, const upb_refcounted *r) {
3245b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (color(t, r) == GREEN) {
3246b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return getattr(t, r) >> 33;
3247b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
3248b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return UINT32_MAX;
3249b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
3250b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
3251b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3252b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void set_lowlink(tarjan *t, const upb_refcounted *r, uint32_t lowlink) {
3253b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(color(t, r) == GREEN);
3254b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  setattr(t, r, ((uint64_t)lowlink << 33) | (getattr(t, r) & 0x1FFFFFFFF));
3255b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
3256b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3257b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic uint32_t *group(tarjan *t, upb_refcounted *r) {
3258b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  uint64_t groupnum;
3259b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_value v;
3260b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bool found;
3261b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3262b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(color(t, r) == WHITE);
3263b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  groupnum = getattr(t, r) >> 8;
3264b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  found = upb_inttable_lookup(&t->groups, groupnum, &v);
3265b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_ASSERT_VAR(found, found);
3266b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_value_getptr(v);
3267b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
3268b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3269b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* If the group leader for this object's group has not previously been set,
3270b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * the given object is assigned to be its leader. */
3271b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic upb_refcounted *groupleader(tarjan *t, upb_refcounted *r) {
3272b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  uint64_t leader_slot;
3273b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_value v;
3274b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bool found;
3275b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3276b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(color(t, r) == WHITE);
3277b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  leader_slot = (getattr(t, r) >> 8) + 1;
3278b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  found = upb_inttable_lookup(&t->groups, leader_slot, &v);
3279b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_ASSERT_VAR(found, found);
3280b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upb_value_getptr(v)) {
3281b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return upb_value_getptr(v);
3282b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
3283b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_inttable_remove(&t->groups, leader_slot, NULL);
3284b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_inttable_insert(&t->groups, leader_slot, upb_value_ptr(r));
3285b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return r;
3286b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
3287b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
3288b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3289b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3290b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Tarjan's algorithm --------------------------------------------------------*/
3291b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3292b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* See:
3293b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *   http://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm */
3294b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void do_tarjan(const upb_refcounted *obj, tarjan *t);
3295b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3296b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void tarjan_visit(const upb_refcounted *obj,
3297b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                         const upb_refcounted *subobj,
3298b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                         void *closure) {
3299b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  tarjan *t = closure;
3300b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (++t->depth > t->maxdepth) {
3301b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_status_seterrf(t->status, "graph too deep to freeze (%d)", t->maxdepth);
3302b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    err(t);
3303b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else if (subobj->is_frozen || color(t, subobj) == WHITE) {
3304b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Do nothing: we don't want to visit or color already-frozen nodes,
3305b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * and WHITE nodes have already been assigned a SCC. */
3306b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else if (color(t, subobj) < GREEN) {
3307b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Subdef has not yet been visited; recurse on it. */
3308b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    do_tarjan(subobj, t);
3309b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    set_lowlink(t, obj, UPB_MIN(lowlink(t, obj), lowlink(t, subobj)));
3310b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else if (color(t, subobj) == GREEN) {
3311b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Subdef is in the stack and hence in the current SCC. */
3312b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    set_lowlink(t, obj, UPB_MIN(lowlink(t, obj), idx(t, subobj)));
3313b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
3314b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  --t->depth;
3315b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
3316b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3317b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void do_tarjan(const upb_refcounted *obj, tarjan *t) {
3318b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (color(t, obj) == BLACK) {
3319b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* We haven't seen this object's group; mark the whole group GRAY. */
3320b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    const upb_refcounted *o = obj;
3321b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    do { set_gray(t, o); } while ((o = o->next) != obj);
3322b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
3323b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3324b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  push(t, obj);
3325b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  visit(obj, tarjan_visit, t);
3326b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (lowlink(t, obj) == idx(t, obj)) {
3327b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    tarjan_newgroup(t);
3328b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    while (pop(t) != obj)
3329b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      ;
3330b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
3331b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
3332b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3333b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3334b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* freeze() ------------------------------------------------------------------*/
3335b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3336b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void crossref(const upb_refcounted *r, const upb_refcounted *subobj,
3337b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                     void *_t) {
3338b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  tarjan *t = _t;
3339b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(color(t, r) > BLACK);
3340b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (color(t, subobj) > BLACK && r->group != subobj->group) {
3341b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Previously this ref was not reflected in subobj->group because they
3342b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * were in the same group; now that they are split a ref must be taken. */
3343b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    refgroup(subobj->group);
3344b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
3345b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
3346b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3347b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool freeze(upb_refcounted *const*roots, int n, upb_status *s,
3348b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                   int maxdepth) {
3349b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  volatile bool ret = false;
3350b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  int i;
3351b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_iter iter;
3352b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3353b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* We run in two passes so that we can allocate all memory before performing
3354b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * any mutation of the input -- this allows us to leave the input unchanged
3355b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * in the case of memory allocation failure. */
3356b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  tarjan t;
3357b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  t.index = 0;
3358b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  t.depth = 0;
3359b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  t.maxdepth = maxdepth;
3360b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  t.status = s;
3361b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!upb_inttable_init(&t.objattr, UPB_CTYPE_UINT64)) goto err1;
3362b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!upb_inttable_init(&t.stack, UPB_CTYPE_PTR)) goto err2;
3363b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!upb_inttable_init(&t.groups, UPB_CTYPE_PTR)) goto err3;
3364b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (setjmp(t.err) != 0) goto err4;
3365b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3366b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3367b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for (i = 0; i < n; i++) {
3368b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (color(&t, roots[i]) < GREEN) {
3369b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      do_tarjan(roots[i], &t);
3370b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
3371b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
3372b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3373b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* If we've made it this far, no further errors are possible so it's safe to
3374b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * mutate the objects without risk of leaving them in an inconsistent state. */
3375b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  ret = true;
3376b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3377b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* The transformation that follows requires care.  The preconditions are:
3378b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * - all objects in attr map are WHITE or GRAY, and are in mutable groups
3379b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   *   (groups of all mutable objs)
3380b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * - no ref2(to, from) refs have incremented count(to) if both "to" and
3381b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   *   "from" are in our attr map (this follows from invariants (2) and (3)) */
3382b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3383b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Pass 1: we remove WHITE objects from their mutable groups, and add them to
3384b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * new groups  according to the SCC's we computed.  These new groups will
3385b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * consist of only frozen objects.  None will be immediately collectible,
3386b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * because WHITE objects are by definition reachable from one of "roots",
3387b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * which the caller must own refs on. */
3388b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_begin(&iter, &t.objattr);
3389b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for(; !upb_inttable_done(&iter); upb_inttable_next(&iter)) {
3390b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_refcounted *obj = (upb_refcounted*)upb_inttable_iter_key(&iter);
3391b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Since removal from a singly-linked list requires access to the object's
3392b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * predecessor, we consider obj->next instead of obj for moving.  With the
3393b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * while() loop we guarantee that we will visit every node's predecessor.
3394b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * Proof:
3395b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     *  1. every node's predecessor is in our attr map.
3396b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     *  2. though the loop body may change a node's predecessor, it will only
3397b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     *     change it to be the node we are currently operating on, so with a
3398b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     *     while() loop we guarantee ourselves the chance to remove each node. */
3399b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    while (color(&t, obj->next) == WHITE &&
3400b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer           group(&t, obj->next) != obj->next->group) {
3401b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_refcounted *leader;
3402b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3403b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      /* Remove from old group. */
3404b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_refcounted *move = obj->next;
3405b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (obj == move) {
3406b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        /* Removing the last object from a group. */
3407b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        assert(*obj->group == obj->individual_count);
3408b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_gfree(obj->group);
3409b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      } else {
3410b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        obj->next = move->next;
3411b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        /* This may decrease to zero; we'll collect GRAY objects (if any) that
3412b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer         * remain in the group in the third pass. */
3413b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        assert(*move->group >= move->individual_count);
3414b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        *move->group -= move->individual_count;
3415b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
3416b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3417b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      /* Add to new group. */
3418b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      leader = groupleader(&t, move);
3419b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (move == leader) {
3420b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        /* First object added to new group is its leader. */
3421b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        move->group = group(&t, move);
3422b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        move->next = move;
3423b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        *move->group = move->individual_count;
3424b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      } else {
3425b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        /* Group already has at least one object in it. */
3426b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        assert(leader->group == group(&t, move));
3427b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        move->group = group(&t, move);
3428b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        move->next = leader->next;
3429b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        leader->next = move;
3430b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        *move->group += move->individual_count;
3431b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
3432b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3433b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      move->is_frozen = true;
3434b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
3435b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
3436b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3437b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Pass 2: GRAY and WHITE objects "obj" with ref2(to, obj) references must
3438b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * increment count(to) if group(obj) != group(to) (which could now be the
3439b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * case if "to" was just frozen). */
3440b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_begin(&iter, &t.objattr);
3441b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for(; !upb_inttable_done(&iter); upb_inttable_next(&iter)) {
3442b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_refcounted *obj = (upb_refcounted*)upb_inttable_iter_key(&iter);
3443b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    visit(obj, crossref, &t);
3444b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
3445b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3446b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Pass 3: GRAY objects are collected if their group's refcount dropped to
3447b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * zero when we removed its white nodes.  This can happen if they had only
3448b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * been kept alive by virtue of sharing a group with an object that was just
3449b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * frozen.
3450b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   *
3451b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * It is important that we do this last, since the GRAY object's free()
3452b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * function could call unref2() on just-frozen objects, which will decrement
3453b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * refs that were added in pass 2. */
3454b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_begin(&iter, &t.objattr);
3455b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for(; !upb_inttable_done(&iter); upb_inttable_next(&iter)) {
3456b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_refcounted *obj = (upb_refcounted*)upb_inttable_iter_key(&iter);
3457b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (obj->group == NULL || *obj->group == 0) {
3458b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (obj->group) {
3459b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_refcounted *o;
3460b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3461b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        /* We eagerly free() the group's count (since we can't easily determine
3462b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer         * the group's remaining size it's the easiest way to ensure it gets
3463b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer         * done). */
3464b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_gfree(obj->group);
3465b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3466b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        /* Visit to release ref2's (done in a separate pass since release_ref2
3467b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer         * depends on o->group being unmodified so it can test merged()). */
3468b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        o = obj;
3469b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        do { visit(o, release_ref2, NULL); } while ((o = o->next) != obj);
3470b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3471b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        /* Mark "group" fields as NULL so we know to free the objects later in
3472b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer         * this loop, but also don't try to delete the group twice. */
3473b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        o = obj;
3474b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        do { o->group = NULL; } while ((o = o->next) != obj);
3475b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
3476b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      freeobj(obj);
3477b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
3478b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
3479b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3480b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammererr4:
3481b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!ret) {
3482b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_inttable_begin(&iter, &t.groups);
3483b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    for(; !upb_inttable_done(&iter); upb_inttable_next(&iter))
3484b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_gfree(upb_value_getptr(upb_inttable_iter_value(&iter)));
3485b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
3486b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_uninit(&t.groups);
3487b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammererr3:
3488b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_uninit(&t.stack);
3489b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammererr2:
3490b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_uninit(&t.objattr);
3491b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammererr1:
3492b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return ret;
3493b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
3494b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3495b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3496b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Misc internal functions  ***************************************************/
3497b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3498b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool merged(const upb_refcounted *r, const upb_refcounted *r2) {
3499b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return r->group == r2->group;
3500b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
3501b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3502b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void merge(upb_refcounted *r, upb_refcounted *from) {
3503b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_refcounted *base;
3504b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_refcounted *tmp;
3505b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3506b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (merged(r, from)) return;
3507b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  *r->group += *from->group;
3508b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_gfree(from->group);
3509b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  base = from;
3510b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3511b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Set all refcount pointers in the "from" chain to the merged refcount.
3512b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   *
3513b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * TODO(haberman): this linear algorithm can result in an overall O(n^2) bound
3514b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * if the user continuously extends a group by one object.  Prevent this by
3515b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * using one of the techniques in this paper:
3516b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   *     ftp://www.ncedc.org/outgoing/geomorph/dino/orals/p245-tarjan.pdf */
3517b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  do { from->group = r->group; } while ((from = from->next) != base);
3518b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3519b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Merge the two circularly linked lists by swapping their next pointers. */
3520b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  tmp = r->next;
3521b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  r->next = base->next;
3522b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  base->next = tmp;
3523b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
3524b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3525b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void unref(const upb_refcounted *r);
3526b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3527b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void release_ref2(const upb_refcounted *obj,
3528b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                         const upb_refcounted *subobj,
3529b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                         void *closure) {
3530b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(closure);
3531b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  untrack(subobj, obj, true);
3532b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!merged(obj, subobj)) {
3533b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    assert(subobj->is_frozen);
3534b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    unref(subobj);
3535b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
3536b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
3537b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3538b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void unref(const upb_refcounted *r) {
3539b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (unrefgroup(r->group)) {
3540b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    const upb_refcounted *o;
3541b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3542b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_gfree(r->group);
3543b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3544b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* In two passes, since release_ref2 needs a guarantee that any subobjs
3545b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * are alive. */
3546b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    o = r;
3547b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    do { visit(o, release_ref2, NULL); } while((o = o->next) != r);
3548b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3549b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    o = r;
3550b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    do {
3551b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      const upb_refcounted *next = o->next;
3552b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      assert(o->is_frozen || o->individual_count == 0);
3553b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      freeobj((upb_refcounted*)o);
3554b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      o = next;
3555b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    } while(o != r);
3556b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
3557b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
3558b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3559b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void freeobj(upb_refcounted *o) {
3560b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  trackfree(o);
3561b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  o->vtbl->free((upb_refcounted*)o);
3562b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
3563b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3564b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3565b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Public interface ***********************************************************/
3566b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3567b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_refcounted_init(upb_refcounted *r,
3568b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                         const struct upb_refcounted_vtbl *vtbl,
3569b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                         const void *owner) {
3570b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#ifndef NDEBUG
3571b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Endianness check.  This is unrelated to upb_refcounted, it's just a
3572b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * convenient place to put the check that we can be assured will run for
3573b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * basically every program using upb. */
3574b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const int x = 1;
3575b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#ifdef UPB_BIG_ENDIAN
3576b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(*(char*)&x != 1);
3577b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#else
3578b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(*(char*)&x == 1);
3579b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#endif
3580b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#endif
3581b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3582b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  r->next = r;
3583b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  r->vtbl = vtbl;
3584b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  r->individual_count = 0;
3585b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  r->is_frozen = false;
3586b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  r->group = upb_gmalloc(sizeof(*r->group));
3587b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!r->group) return false;
3588b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  *r->group = 0;
3589b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  trackinit(r);
3590b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_refcounted_ref(r, owner);
3591b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
3592b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
3593b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3594b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_refcounted_isfrozen(const upb_refcounted *r) {
3595b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return r->is_frozen;
3596b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
3597b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3598b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_refcounted_ref(const upb_refcounted *r, const void *owner) {
3599b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  track(r, owner, false);
3600b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!r->is_frozen)
3601b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    ((upb_refcounted*)r)->individual_count++;
3602b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  refgroup(r->group);
3603b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
3604b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3605b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_refcounted_unref(const upb_refcounted *r, const void *owner) {
3606b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  untrack(r, owner, false);
3607b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!r->is_frozen)
3608b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    ((upb_refcounted*)r)->individual_count--;
3609b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  unref(r);
3610b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
3611b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3612b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_refcounted_ref2(const upb_refcounted *r, upb_refcounted *from) {
3613b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(!from->is_frozen);  /* Non-const pointer implies this. */
3614b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  track(r, from, true);
3615b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (r->is_frozen) {
3616b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    refgroup(r->group);
3617b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
3618b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    merge((upb_refcounted*)r, from);
3619b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
3620b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
3621b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3622b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_refcounted_unref2(const upb_refcounted *r, upb_refcounted *from) {
3623b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(!from->is_frozen);  /* Non-const pointer implies this. */
3624b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  untrack(r, from, true);
3625b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (r->is_frozen) {
3626b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    unref(r);
3627b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
3628b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    assert(merged(r, from));
3629b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
3630b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
3631b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3632b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_refcounted_donateref(
3633b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    const upb_refcounted *r, const void *from, const void *to) {
3634b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(from != to);
3635b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (to != NULL)
3636b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_refcounted_ref(r, to);
3637b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (from != NULL)
3638b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_refcounted_unref(r, from);
3639b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
3640b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3641b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_refcounted_checkref(const upb_refcounted *r, const void *owner) {
3642b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  checkref(r, owner, false);
3643b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
3644b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3645b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_refcounted_freeze(upb_refcounted *const*roots, int n, upb_status *s,
3646b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                           int maxdepth) {
3647b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  int i;
3648b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bool ret;
3649b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for (i = 0; i < n; i++) {
3650b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    assert(!roots[i]->is_frozen);
3651b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
3652b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  ret = freeze(roots, n, s, maxdepth);
3653b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(!s || ret == upb_ok(s));
3654b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return ret;
3655b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
3656b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3657b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3658b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Fallback implementation if the shim is not specialized by the JIT. */
3659b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#define SHIM_WRITER(type, ctype)                                              \
3660b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bool upb_shim_set ## type (void *c, const void *hd, ctype val) {            \
3661b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    uint8_t *m = c;                                                           \
3662b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    const upb_shim_data *d = hd;                                              \
3663b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (d->hasbit > 0)                                                        \
3664b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      *(uint8_t*)&m[d->hasbit / 8] |= 1 << (d->hasbit % 8);                   \
3665b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    *(ctype*)&m[d->offset] = val;                                             \
3666b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return true;                                                              \
3667b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }                                                                           \
3668b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3669b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerSHIM_WRITER(double, double)
3670b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerSHIM_WRITER(float,  float)
3671b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerSHIM_WRITER(int32,  int32_t)
3672b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerSHIM_WRITER(int64,  int64_t)
3673b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerSHIM_WRITER(uint32, uint32_t)
3674b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerSHIM_WRITER(uint64, uint64_t)
3675b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerSHIM_WRITER(bool,   bool)
3676b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#undef SHIM_WRITER
3677b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3678b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_shim_set(upb_handlers *h, const upb_fielddef *f, size_t offset,
3679b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                  int32_t hasbit) {
3680b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
3681b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bool ok;
3682b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3683b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_shim_data *d = upb_gmalloc(sizeof(*d));
3684b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!d) return false;
3685b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  d->offset = offset;
3686b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  d->hasbit = hasbit;
3687b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3688b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_handlerattr_sethandlerdata(&attr, d);
3689b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_handlerattr_setalwaysok(&attr, true);
3690b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_handlers_addcleanup(h, d, upb_gfree);
3691b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3692b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#define TYPE(u, l) \
3693b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  case UPB_TYPE_##u: \
3694b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    ok = upb_handlers_set##l(h, f, upb_shim_set##l, &attr); break;
3695b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3696b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  ok = false;
3697b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3698b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  switch (upb_fielddef_type(f)) {
3699b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    TYPE(INT64,  int64);
3700b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    TYPE(INT32,  int32);
3701b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    TYPE(ENUM,   int32);
3702b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    TYPE(UINT64, uint64);
3703b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    TYPE(UINT32, uint32);
3704b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    TYPE(DOUBLE, double);
3705b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    TYPE(FLOAT,  float);
3706b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    TYPE(BOOL,   bool);
3707b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    default: assert(false); break;
3708b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
3709b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#undef TYPE
3710b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3711b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_handlerattr_uninit(&attr);
3712b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return ok;
3713b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
3714b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3715b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_shim_data *upb_shim_getdata(const upb_handlers *h, upb_selector_t s,
3716b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                      upb_fieldtype_t *type) {
3717b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_func *f = upb_handlers_gethandler(h, s);
3718b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3719b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if ((upb_int64_handlerfunc*)f == upb_shim_setint64) {
3720b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    *type = UPB_TYPE_INT64;
3721b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else if ((upb_int32_handlerfunc*)f == upb_shim_setint32) {
3722b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    *type = UPB_TYPE_INT32;
3723b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else if ((upb_uint64_handlerfunc*)f == upb_shim_setuint64) {
3724b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    *type = UPB_TYPE_UINT64;
3725b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else if ((upb_uint32_handlerfunc*)f == upb_shim_setuint32) {
3726b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    *type = UPB_TYPE_UINT32;
3727b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else if ((upb_double_handlerfunc*)f == upb_shim_setdouble) {
3728b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    *type = UPB_TYPE_DOUBLE;
3729b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else if ((upb_float_handlerfunc*)f == upb_shim_setfloat) {
3730b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    *type = UPB_TYPE_FLOAT;
3731b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else if ((upb_bool_handlerfunc*)f == upb_shim_setbool) {
3732b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    *type = UPB_TYPE_BOOL;
3733b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
3734b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return NULL;
3735b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
3736b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3737b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return (const upb_shim_data*)upb_handlers_gethandlerdata(h, s);
3738b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
3739b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3740b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3741b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <string.h>
3742b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3743b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void upb_symtab_free(upb_refcounted *r) {
3744b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_symtab *s = (upb_symtab*)r;
3745b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_strtable_iter i;
3746b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_strtable_begin(&i, &s->symtab);
3747b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for (; !upb_strtable_done(&i); upb_strtable_next(&i)) {
3748b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    const upb_def *def = upb_value_getptr(upb_strtable_iter_value(&i));
3749b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_def_unref(def, s);
3750b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
3751b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_strtable_uninit(&s->symtab);
3752b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_gfree(s);
3753b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
3754b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3755b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerupb_symtab *upb_symtab_new(const void *owner) {
3756b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  static const struct upb_refcounted_vtbl vtbl = {NULL, &upb_symtab_free};
3757b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3758b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_symtab *s = upb_gmalloc(sizeof(*s));
3759b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!s) {
3760b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return NULL;
3761b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
3762b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3763b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_refcounted_init(upb_symtab_upcast_mutable(s), &vtbl, owner);
3764b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_strtable_init(&s->symtab, UPB_CTYPE_PTR);
3765b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return s;
3766b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
3767b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3768b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_symtab_freeze(upb_symtab *s) {
3769b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_refcounted *r;
3770b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bool ok;
3771b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3772b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(!upb_symtab_isfrozen(s));
3773b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  r = upb_symtab_upcast_mutable(s);
3774b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* The symtab does not take ref2's (see refcounted.h) on the defs, because
3775b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * defs cannot refer back to the table and therefore cannot create cycles.  So
3776b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * 0 will suffice for maxdepth here. */
3777b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  ok = upb_refcounted_freeze(&r, 1, NULL, 0);
3778b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_ASSERT_VAR(ok, ok);
3779b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
3780b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3781b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_def *upb_symtab_lookup(const upb_symtab *s, const char *sym) {
3782b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_value v;
3783b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_def *ret = upb_strtable_lookup(&s->symtab, sym, &v) ?
3784b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_value_getptr(v) : NULL;
3785b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return ret;
3786b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
3787b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3788b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_msgdef *upb_symtab_lookupmsg(const upb_symtab *s, const char *sym) {
3789b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_value v;
3790b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_def *def = upb_strtable_lookup(&s->symtab, sym, &v) ?
3791b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_value_getptr(v) : NULL;
3792b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return def ? upb_dyncast_msgdef(def) : NULL;
3793b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
3794b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3795b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_enumdef *upb_symtab_lookupenum(const upb_symtab *s, const char *sym) {
3796b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_value v;
3797b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_def *def = upb_strtable_lookup(&s->symtab, sym, &v) ?
3798b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_value_getptr(v) : NULL;
3799b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return def ? upb_dyncast_enumdef(def) : NULL;
3800b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
3801b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3802b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Given a symbol and the base symbol inside which it is defined, find the
3803b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * symbol's definition in t. */
3804b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic upb_def *upb_resolvename(const upb_strtable *t,
3805b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                const char *base, const char *sym) {
3806b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if(strlen(sym) == 0) return NULL;
3807b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if(sym[0] == '.') {
3808b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Symbols starting with '.' are absolute, so we do a single lookup.
3809b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * Slice to omit the leading '.' */
3810b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_value v;
3811b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return upb_strtable_lookup(t, sym + 1, &v) ? upb_value_getptr(v) : NULL;
3812b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
3813b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Remove components from base until we find an entry or run out.
3814b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * TODO: This branch is totally broken, but currently not used. */
3815b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    (void)base;
3816b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    assert(false);
3817b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return NULL;
3818b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
3819b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
3820b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3821b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_def *upb_symtab_resolve(const upb_symtab *s, const char *base,
3822b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                  const char *sym) {
3823b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_def *ret = upb_resolvename(&s->symtab, base, sym);
3824b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return ret;
3825b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
3826b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3827b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Starts a depth-first traversal at "def", recursing into any subdefs
3828b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * (ie. submessage types).  Adds duplicates of existing defs to addtab
3829b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * wherever necessary, so that the resulting symtab will be consistent once
3830b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * addtab is added.
3831b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *
3832b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * More specifically, if any def D is found in the DFS that:
3833b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *
3834b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *   1. can reach a def that is being replaced by something in addtab, AND
3835b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *
3836b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *   2. is not itself being replaced already (ie. this name doesn't already
3837b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *      exist in addtab)
3838b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *
3839b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * ...then a duplicate (new copy) of D will be added to addtab.
3840b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *
3841b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Returns true if this happened for any def reachable from "def."
3842b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *
3843b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * It is slightly tricky to do this correctly in the presence of cycles.  If we
3844b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * detect that our DFS has hit a cycle, we might not yet know if any SCCs on
3845b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * our stack can reach a def in addtab or not.  Once we figure this out, that
3846b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * answer needs to apply to *all* defs in these SCCs, even if we visited them
3847b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * already.  So a straight up one-pass cycle-detecting DFS won't work.
3848b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *
3849b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * To work around this problem, we traverse each SCC (which we already
3850b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * computed, since these defs are frozen) as a single node.  We first compute
3851b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * whether the SCC as a whole can reach any def in addtab, then we dup (or not)
3852b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * the entire SCC.  This requires breaking the encapsulation of upb_refcounted,
3853b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * since that is where we get the data about what SCC we are in. */
3854b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool upb_resolve_dfs(const upb_def *def, upb_strtable *addtab,
3855b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                            const void *new_owner, upb_inttable *seen,
3856b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                            upb_status *s) {
3857b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_value v;
3858b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bool need_dup;
3859b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const upb_def *base;
3860b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const void* memoize_key;
3861b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3862b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Memoize results of this function for efficiency (since we're traversing a
3863b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * DAG this is not needed to limit the depth of the search).
3864b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   *
3865b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * We memoize by SCC instead of by individual def. */
3866b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  memoize_key = def->base.group;
3867b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3868b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upb_inttable_lookupptr(seen, memoize_key, &v))
3869b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return upb_value_getbool(v);
3870b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3871b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Visit submessages for all messages in the SCC. */
3872b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  need_dup = false;
3873b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  base = def;
3874b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  do {
3875b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_value v;
3876b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    const upb_msgdef *m;
3877b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3878b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    assert(upb_def_isfrozen(def));
3879b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (def->type == UPB_DEF_FIELD) continue;
3880b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (upb_strtable_lookup(addtab, upb_def_fullname(def), &v)) {
3881b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      need_dup = true;
3882b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
3883b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3884b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* For messages, continue the recursion by visiting all subdefs, but only
3885b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * ones in different SCCs. */
3886b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    m = upb_dyncast_msgdef(def);
3887b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (m) {
3888b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_msg_field_iter i;
3889b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      for(upb_msg_field_begin(&i, m);
3890b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          !upb_msg_field_done(&i);
3891b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          upb_msg_field_next(&i)) {
3892b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_fielddef *f = upb_msg_iter_field(&i);
3893b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        const upb_def *subdef;
3894b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3895b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        if (!upb_fielddef_hassubdef(f)) continue;
3896b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        subdef = upb_fielddef_subdef(f);
3897b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3898b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        /* Skip subdefs in this SCC. */
3899b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        if (def->base.group == subdef->base.group) continue;
3900b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3901b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        /* |= to avoid short-circuit; we need its side-effects. */
3902b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        need_dup |= upb_resolve_dfs(subdef, addtab, new_owner, seen, s);
3903b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        if (!upb_ok(s)) return false;
3904b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
3905b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
3906b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } while ((def = (upb_def*)def->base.next) != base);
3907b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3908b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (need_dup) {
3909b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Dup all defs in this SCC that don't already have entries in addtab. */
3910b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    def = base;
3911b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    do {
3912b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      const char *name;
3913b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3914b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (def->type == UPB_DEF_FIELD) continue;
3915b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      name = upb_def_fullname(def);
3916b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (!upb_strtable_lookup(addtab, name, NULL)) {
3917b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_def *newdef = upb_def_dup(def, new_owner);
3918b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        if (!newdef) goto oom;
3919b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        newdef->came_from_user = false;
3920b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        if (!upb_strtable_insert(addtab, name, upb_value_ptr(newdef)))
3921b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          goto oom;
3922b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
3923b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    } while ((def = (upb_def*)def->base.next) != base);
3924b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
3925b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3926b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_insertptr(seen, memoize_key, upb_value_bool(need_dup));
3927b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return need_dup;
3928b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3929b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammeroom:
3930b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_status_seterrmsg(s, "out of memory");
3931b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return false;
3932b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
3933b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3934b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* TODO(haberman): we need a lot more testing of error conditions.
3935b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * The came_from_user stuff in particular is not tested. */
3936b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool symtab_add(upb_symtab *s, upb_def *const*defs, size_t n,
3937b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                       void *ref_donor, upb_refcounted *freeze_also,
3938b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                       upb_status *status) {
3939b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  size_t i;
3940b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  size_t add_n;
3941b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  size_t freeze_n;
3942b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_strtable_iter iter;
3943b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_refcounted **add_objs = NULL;
3944b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_def **add_defs = NULL;
3945b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  size_t add_objs_size;
3946b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_strtable addtab;
3947b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable seen;
3948b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3949b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (n == 0 && !freeze_also) {
3950b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return true;
3951b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
3952b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3953b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(!upb_symtab_isfrozen(s));
3954b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!upb_strtable_init(&addtab, UPB_CTYPE_PTR)) {
3955b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_status_seterrmsg(status, "out of memory");
3956b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
3957b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
3958b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3959b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Add new defs to our "add" set. */
3960b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for (i = 0; i < n; i++) {
3961b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_def *def = defs[i];
3962b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    const char *fullname;
3963b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_fielddef *f;
3964b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3965b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (upb_def_isfrozen(def)) {
3966b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_status_seterrmsg(status, "added defs must be mutable");
3967b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      goto err;
3968b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
3969b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    assert(!upb_def_isfrozen(def));
3970b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    fullname = upb_def_fullname(def);
3971b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (!fullname) {
3972b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_status_seterrmsg(
3973b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          status, "Anonymous defs cannot be added to a symtab");
3974b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      goto err;
3975b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
3976b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3977b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    f = upb_dyncast_fielddef_mutable(def);
3978b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
3979b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (f) {
3980b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (!upb_fielddef_containingtypename(f)) {
3981b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_status_seterrmsg(status,
3982b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                             "Standalone fielddefs must have a containing type "
3983b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                             "(extendee) name set");
3984b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        goto err;
3985b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
3986b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    } else {
3987b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (upb_strtable_lookup(&addtab, fullname, NULL)) {
3988b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_status_seterrf(status, "Conflicting defs named '%s'", fullname);
3989b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        goto err;
3990b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
3991b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      /* We need this to back out properly, because if there is a failure we
3992b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer       * need to donate the ref back to the caller. */
3993b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      def->came_from_user = true;
3994b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_def_donateref(def, ref_donor, s);
3995b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (!upb_strtable_insert(&addtab, fullname, upb_value_ptr(def)))
3996b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        goto oom_err;
3997b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
3998b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
3999b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4000b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Add standalone fielddefs (ie. extensions) to the appropriate messages.
4001b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * If the appropriate message only exists in the existing symtab, duplicate
4002b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * it so we have a mutable copy we can add the fields to. */
4003b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for (i = 0; i < n; i++) {
4004b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_def *def = defs[i];
4005b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_fielddef *f = upb_dyncast_fielddef_mutable(def);
4006b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    const char *msgname;
4007b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_value v;
4008b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_msgdef *m;
4009b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4010b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (!f) continue;
4011b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    msgname = upb_fielddef_containingtypename(f);
4012b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* We validated this earlier in this function. */
4013b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    assert(msgname);
4014b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4015b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* If the extendee name is absolutely qualified, move past the initial ".".
4016b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * TODO(haberman): it is not obvious what it would mean if this was not
4017b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * absolutely qualified. */
4018b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (msgname[0] == '.') {
4019b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      msgname++;
4020b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
4021b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4022b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (upb_strtable_lookup(&addtab, msgname, &v)) {
4023b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      /* Extendee is in the set of defs the user asked us to add. */
4024b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      m = upb_value_getptr(v);
4025b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    } else {
4026b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      /* Need to find and dup the extendee from the existing symtab. */
4027b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      const upb_msgdef *frozen_m = upb_symtab_lookupmsg(s, msgname);
4028b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (!frozen_m) {
4029b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_status_seterrf(status,
4030b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                           "Tried to extend message %s that does not exist "
4031b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                           "in this SymbolTable.",
4032b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                           msgname);
4033b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        goto err;
4034b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
4035b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      m = upb_msgdef_dup(frozen_m, s);
4036b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (!m) goto oom_err;
4037b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (!upb_strtable_insert(&addtab, msgname, upb_value_ptr(m))) {
4038b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_msgdef_unref(m, s);
4039b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        goto oom_err;
4040b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
4041b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
4042b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4043b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (!upb_msgdef_addfield(m, f, ref_donor, status)) {
4044b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      goto err;
4045b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
4046b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
4047b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4048b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Add dups of any existing def that can reach a def with the same name as
4049b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * anything in our "add" set. */
4050b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!upb_inttable_init(&seen, UPB_CTYPE_BOOL)) goto oom_err;
4051b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_strtable_begin(&iter, &s->symtab);
4052b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for (; !upb_strtable_done(&iter); upb_strtable_next(&iter)) {
4053b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_def *def = upb_value_getptr(upb_strtable_iter_value(&iter));
4054b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_resolve_dfs(def, &addtab, s, &seen, status);
4055b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (!upb_ok(status)) goto err;
4056b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
4057b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_uninit(&seen);
4058b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4059b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Now using the table, resolve symbolic references for subdefs. */
4060b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_strtable_begin(&iter, &addtab);
4061b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for (; !upb_strtable_done(&iter); upb_strtable_next(&iter)) {
4062b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    const char *base;
4063b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_def *def = upb_value_getptr(upb_strtable_iter_value(&iter));
4064b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_msgdef *m = upb_dyncast_msgdef_mutable(def);
4065b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_msg_field_iter j;
4066b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4067b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (!m) continue;
4068b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Type names are resolved relative to the message in which they appear. */
4069b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    base = upb_msgdef_fullname(m);
4070b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4071b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    for(upb_msg_field_begin(&j, m);
4072b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        !upb_msg_field_done(&j);
4073b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_msg_field_next(&j)) {
4074b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_fielddef *f = upb_msg_iter_field(&j);
4075b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      const char *name = upb_fielddef_subdefname(f);
4076b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (name && !upb_fielddef_subdef(f)) {
4077b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        /* Try the lookup in the current set of to-be-added defs first. If not
4078b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer         * there, try existing defs. */
4079b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_def *subdef = upb_resolvename(&addtab, base, name);
4080b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        if (subdef == NULL) {
4081b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          subdef = upb_resolvename(&s->symtab, base, name);
4082b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        }
4083b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        if (subdef == NULL) {
4084b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          upb_status_seterrf(
4085b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer              status, "couldn't resolve name '%s' in message '%s'", name, base);
4086b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          goto err;
4087b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        } else if (!upb_fielddef_setsubdef(f, subdef, status)) {
4088b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          goto err;
4089b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        }
4090b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
4091b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
4092b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
4093b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4094b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* We need an array of the defs in addtab, for passing to
4095b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * upb_refcounted_freeze(). */
4096b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  add_objs_size = upb_strtable_count(&addtab);
4097b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (freeze_also) {
4098b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    add_objs_size++;
4099b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
4100b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4101b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  add_defs = upb_gmalloc(sizeof(void*) * add_objs_size);
4102b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (add_defs == NULL) goto oom_err;
4103b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_strtable_begin(&iter, &addtab);
4104b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for (add_n = 0; !upb_strtable_done(&iter); upb_strtable_next(&iter)) {
4105b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    add_defs[add_n++] = upb_value_getptr(upb_strtable_iter_value(&iter));
4106b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
4107b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4108b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Validate defs. */
4109b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!_upb_def_validate(add_defs, add_n, status)) {
4110b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    goto err;
4111b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
4112b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4113b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Cheat a little and give the array a new type.
4114b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * This is probably undefined behavior, but this code will be deleted soon. */
4115b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  add_objs = (upb_refcounted**)add_defs;
4116b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4117b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  freeze_n = add_n;
4118b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (freeze_also) {
4119b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    add_objs[freeze_n++] = freeze_also;
4120b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
4121b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4122b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!upb_refcounted_freeze(add_objs, freeze_n, status,
4123b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                             UPB_MAX_MESSAGE_DEPTH * 2)) {
4124b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    goto err;
4125b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
4126b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4127b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* This must be delayed until all errors have been detected, since error
4128b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * recovery code uses this table to cleanup defs. */
4129b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_strtable_uninit(&addtab);
4130b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4131b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* TODO(haberman) we don't properly handle errors after this point (like
4132b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * OOM in upb_strtable_insert() below). */
4133b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for (i = 0; i < add_n; i++) {
4134b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_def *def = (upb_def*)add_objs[i];
4135b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    const char *name = upb_def_fullname(def);
4136b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_value v;
4137b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    bool success;
4138b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4139b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (upb_strtable_remove(&s->symtab, name, &v)) {
4140b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      const upb_def *def = upb_value_getptr(v);
4141b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_def_unref(def, s);
4142b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
4143b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    success = upb_strtable_insert(&s->symtab, name, upb_value_ptr(def));
4144b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    UPB_ASSERT_VAR(success, success == true);
4145b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
4146b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_gfree(add_defs);
4147b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
4148b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4149b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammeroom_err:
4150b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_status_seterrmsg(status, "out of memory");
4151b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammererr: {
4152b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* For defs the user passed in, we need to donate the refs back.  For defs
4153b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * we dup'd, we need to just unref them. */
4154b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_strtable_begin(&iter, &addtab);
4155b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    for (; !upb_strtable_done(&iter); upb_strtable_next(&iter)) {
4156b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_def *def = upb_value_getptr(upb_strtable_iter_value(&iter));
4157b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      bool came_from_user = def->came_from_user;
4158b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      def->came_from_user = false;
4159b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (came_from_user) {
4160b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_def_donateref(def, s, ref_donor);
4161b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      } else {
4162b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_def_unref(def, s);
4163b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
4164b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
4165b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
4166b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_strtable_uninit(&addtab);
4167b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_gfree(add_defs);
4168b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(!upb_ok(status));
4169b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return false;
4170b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4171b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4172b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_symtab_add(upb_symtab *s, upb_def *const*defs, size_t n,
4173b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                    void *ref_donor, upb_status *status) {
4174b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return symtab_add(s, defs, n, ref_donor, NULL, status);
4175b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4176b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4177b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_symtab_addfile(upb_symtab *s, upb_filedef *file, upb_status *status) {
4178b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  size_t n;
4179b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  size_t i;
4180b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_def **defs;
4181b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bool ret;
4182b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4183b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  n = upb_filedef_defcount(file);
4184b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  defs = upb_gmalloc(sizeof(*defs) * n);
4185b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4186b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (defs == NULL) {
4187b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_status_seterrmsg(status, "Out of memory");
4188b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
4189b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
4190b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4191b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for (i = 0; i < n; i++) {
4192b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    defs[i] = upb_filedef_mutabledef(file, i);
4193b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
4194b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4195b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  ret = symtab_add(s, defs, n, NULL, upb_filedef_upcast_mutable(file), status);
4196b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4197b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_gfree(defs);
4198b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return ret;
4199b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4200b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4201b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Iteration. */
4202b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4203b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void advance_to_matching(upb_symtab_iter *iter) {
4204b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (iter->type == UPB_DEF_ANY)
4205b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return;
4206b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4207b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  while (!upb_strtable_done(&iter->iter) &&
4208b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer         iter->type != upb_symtab_iter_def(iter)->type) {
4209b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_strtable_next(&iter->iter);
4210b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
4211b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4212b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4213b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_symtab_begin(upb_symtab_iter *iter, const upb_symtab *s,
4214b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                      upb_deftype_t type) {
4215b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_strtable_begin(&iter->iter, &s->symtab);
4216b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  iter->type = type;
4217b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  advance_to_matching(iter);
4218b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4219b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4220b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_symtab_next(upb_symtab_iter *iter) {
4221b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_strtable_next(&iter->iter);
4222b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  advance_to_matching(iter);
4223b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4224b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4225b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_symtab_done(const upb_symtab_iter *iter) {
4226b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_strtable_done(&iter->iter);
4227b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4228b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4229b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_def *upb_symtab_iter_def(const upb_symtab_iter *iter) {
4230b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_value_getptr(upb_strtable_iter_value(&iter->iter));
4231b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4232b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/*
4233b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** upb_table Implementation
4234b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer**
4235b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** Implementation is heavily inspired by Lua's ltable.c.
4236b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer*/
4237b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4238b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4239b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <string.h>
4240b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4241b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#define UPB_MAXARRSIZE 16  /* 64k. */
4242b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4243b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* From Chromium. */
4244b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#define ARRAY_SIZE(x) \
4245b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x])))))
4246b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4247b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#ifdef NDEBUG
4248b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void upb_check_alloc(upb_table *t, upb_alloc *a) {
4249b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(t);
4250b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(a);
4251b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4252b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#else
4253b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void upb_check_alloc(upb_table *t, upb_alloc *a) {
4254b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(t->alloc == a);
4255b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4256b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#endif
4257b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4258b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic const double MAX_LOAD = 0.85;
4259b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4260b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* The minimum utilization of the array part of a mixed hash/array table.  This
4261b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * is a speed/memory-usage tradeoff (though it's not straightforward because of
4262b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * cache effects).  The lower this is, the more memory we'll use. */
4263b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic const double MIN_DENSITY = 0.1;
4264b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4265b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool is_pow2(uint64_t v) { return v == 0 || (v & (v - 1)) == 0; }
4266b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4267b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerint log2ceil(uint64_t v) {
4268b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  int ret = 0;
4269b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bool pow2 = is_pow2(v);
4270b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  while (v >>= 1) ret++;
4271b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  ret = pow2 ? ret : ret + 1;  /* Ceiling. */
4272b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return UPB_MIN(UPB_MAXARRSIZE, ret);
4273b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4274b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4275b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerchar *upb_strdup(const char *s, upb_alloc *a) {
4276b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_strdup2(s, strlen(s), a);
4277b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4278b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4279b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerchar *upb_strdup2(const char *s, size_t len, upb_alloc *a) {
4280b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  size_t n;
4281b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  char *p;
4282b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4283b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Prevent overflow errors. */
4284b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (len == SIZE_MAX) return NULL;
4285b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Always null-terminate, even if binary data; but don't rely on the input to
4286b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * have a null-terminating byte since it may be a raw binary buffer. */
4287b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  n = len + 1;
4288b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  p = upb_malloc(a, n);
4289b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (p) {
4290b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    memcpy(p, s, len);
4291b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    p[len] = 0;
4292b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
4293b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return p;
4294b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4295b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4296b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* A type to represent the lookup key of either a strtable or an inttable. */
4297b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammertypedef union {
4298b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  uintptr_t num;
4299b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  struct {
4300b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    const char *str;
4301b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    size_t len;
4302b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } str;
4303b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer} lookupkey_t;
4304b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4305b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic lookupkey_t strkey2(const char *str, size_t len) {
4306b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  lookupkey_t k;
4307b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  k.str.str = str;
4308b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  k.str.len = len;
4309b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return k;
4310b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4311b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4312b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic lookupkey_t intkey(uintptr_t key) {
4313b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  lookupkey_t k;
4314b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  k.num = key;
4315b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return k;
4316b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4317b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4318b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammertypedef uint32_t hashfunc_t(upb_tabkey key);
4319b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammertypedef bool eqlfunc_t(upb_tabkey k1, lookupkey_t k2);
4320b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4321b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Base table (shared code) ***************************************************/
4322b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4323b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* For when we need to cast away const. */
4324b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic upb_tabent *mutable_entries(upb_table *t) {
4325b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return (upb_tabent*)t->entries;
4326b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4327b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4328b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool isfull(upb_table *t) {
4329b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upb_table_size(t) == 0) {
4330b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return true;
4331b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
4332b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return ((double)(t->count + 1) / upb_table_size(t)) > MAX_LOAD;
4333b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
4334b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4335b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4336b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool init(upb_table *t, upb_ctype_t ctype, uint8_t size_lg2,
4337b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                 upb_alloc *a) {
4338b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  size_t bytes;
4339b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4340b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  t->count = 0;
4341b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  t->ctype = ctype;
4342b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  t->size_lg2 = size_lg2;
4343b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  t->mask = upb_table_size(t) ? upb_table_size(t) - 1 : 0;
4344b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#ifndef NDEBUG
4345b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  t->alloc = a;
4346b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#endif
4347b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bytes = upb_table_size(t) * sizeof(upb_tabent);
4348b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (bytes > 0) {
4349b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    t->entries = upb_malloc(a, bytes);
4350b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (!t->entries) return false;
4351b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    memset(mutable_entries(t), 0, bytes);
4352b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
4353b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    t->entries = NULL;
4354b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
4355b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
4356b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4357b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4358b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void uninit(upb_table *t, upb_alloc *a) {
4359b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_check_alloc(t, a);
4360b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_free(a, mutable_entries(t));
4361b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4362b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4363b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic upb_tabent *emptyent(upb_table *t) {
4364b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_tabent *e = mutable_entries(t) + upb_table_size(t);
4365b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  while (1) { if (upb_tabent_isempty(--e)) return e; assert(e > t->entries); }
4366b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4367b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4368b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic upb_tabent *getentry_mutable(upb_table *t, uint32_t hash) {
4369b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return (upb_tabent*)upb_getentry(t, hash);
4370b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4371b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4372b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic const upb_tabent *findentry(const upb_table *t, lookupkey_t key,
4373b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                   uint32_t hash, eqlfunc_t *eql) {
4374b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const upb_tabent *e;
4375b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4376b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (t->size_lg2 == 0) return NULL;
4377b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  e = upb_getentry(t, hash);
4378b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upb_tabent_isempty(e)) return NULL;
4379b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  while (1) {
4380b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (eql(e->key, key)) return e;
4381b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if ((e = e->next) == NULL) return NULL;
4382b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
4383b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4384b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4385b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic upb_tabent *findentry_mutable(upb_table *t, lookupkey_t key,
4386b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                     uint32_t hash, eqlfunc_t *eql) {
4387b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return (upb_tabent*)findentry(t, key, hash, eql);
4388b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4389b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4390b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool lookup(const upb_table *t, lookupkey_t key, upb_value *v,
4391b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                   uint32_t hash, eqlfunc_t *eql) {
4392b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const upb_tabent *e = findentry(t, key, hash, eql);
4393b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (e) {
4394b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (v) {
4395b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      _upb_value_setval(v, e->val.val, t->ctype);
4396b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
4397b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return true;
4398b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
4399b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
4400b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
4401b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4402b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4403b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* The given key must not already exist in the table. */
4404b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void insert(upb_table *t, lookupkey_t key, upb_tabkey tabkey,
4405b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                   upb_value val, uint32_t hash,
4406b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                   hashfunc_t *hashfunc, eqlfunc_t *eql) {
4407b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_tabent *mainpos_e;
4408b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_tabent *our_e;
4409b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4410b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(eql);
4411b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(key);
4412b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(findentry(t, key, hash, eql) == NULL);
4413b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(val.ctype == t->ctype);
4414b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4415b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  t->count++;
4416b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  mainpos_e = getentry_mutable(t, hash);
4417b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  our_e = mainpos_e;
4418b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4419b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upb_tabent_isempty(mainpos_e)) {
4420b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Our main position is empty; use it. */
4421b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    our_e->next = NULL;
4422b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
4423b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Collision. */
4424b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_tabent *new_e = emptyent(t);
4425b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Head of collider's chain. */
4426b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_tabent *chain = getentry_mutable(t, hashfunc(mainpos_e->key));
4427b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (chain == mainpos_e) {
4428b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      /* Existing ent is in its main posisiton (it has the same hash as us, and
4429b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer       * is the head of our chain).  Insert to new ent and append to this chain. */
4430b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      new_e->next = mainpos_e->next;
4431b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      mainpos_e->next = new_e;
4432b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      our_e = new_e;
4433b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    } else {
4434b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      /* Existing ent is not in its main position (it is a node in some other
4435b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer       * chain).  This implies that no existing ent in the table has our hash.
4436b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer       * Evict it (updating its chain) and use its ent for head of our chain. */
4437b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      *new_e = *mainpos_e;  /* copies next. */
4438b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      while (chain->next != mainpos_e) {
4439b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        chain = (upb_tabent*)chain->next;
4440b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        assert(chain);
4441b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
4442b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      chain->next = new_e;
4443b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      our_e = mainpos_e;
4444b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      our_e->next = NULL;
4445b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
4446b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
4447b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  our_e->key = tabkey;
4448b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  our_e->val.val = val.val;
4449b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(findentry(t, key, hash, eql) == our_e);
4450b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4451b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4452b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool rm(upb_table *t, lookupkey_t key, upb_value *val,
4453b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer               upb_tabkey *removed, uint32_t hash, eqlfunc_t *eql) {
4454b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_tabent *chain = getentry_mutable(t, hash);
4455b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upb_tabent_isempty(chain)) return false;
4456b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (eql(chain->key, key)) {
4457b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Element to remove is at the head of its chain. */
4458b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    t->count--;
4459b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (val) {
4460b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      _upb_value_setval(val, chain->val.val, t->ctype);
4461b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
4462b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (chain->next) {
4463b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_tabent *move = (upb_tabent*)chain->next;
4464b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      *chain = *move;
4465b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (removed) *removed = move->key;
4466b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      move->key = 0;  /* Make the slot empty. */
4467b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    } else {
4468b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (removed) *removed = chain->key;
4469b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      chain->key = 0;  /* Make the slot empty. */
4470b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
4471b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return true;
4472b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
4473b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Element to remove is either in a non-head position or not in the
4474b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * table. */
4475b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    while (chain->next && !eql(chain->next->key, key))
4476b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      chain = (upb_tabent*)chain->next;
4477b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (chain->next) {
4478b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      /* Found element to remove. */
4479b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_tabent *rm;
4480b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4481b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (val) {
4482b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        _upb_value_setval(val, chain->next->val.val, t->ctype);
4483b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
4484b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      rm = (upb_tabent*)chain->next;
4485b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (removed) *removed = rm->key;
4486b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      rm->key = 0;
4487b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      chain->next = rm->next;
4488b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      t->count--;
4489b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return true;
4490b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    } else {
4491b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return false;
4492b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
4493b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
4494b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4495b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4496b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic size_t next(const upb_table *t, size_t i) {
4497b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  do {
4498b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (++i >= upb_table_size(t))
4499b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return SIZE_MAX;
4500b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } while(upb_tabent_isempty(&t->entries[i]));
4501b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4502b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return i;
4503b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4504b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4505b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic size_t begin(const upb_table *t) {
4506b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return next(t, -1);
4507b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4508b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4509b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4510b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* upb_strtable ***************************************************************/
4511b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4512b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* A simple "subclass" of upb_table that only adds a hash function for strings. */
4513b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4514b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic upb_tabkey strcopy(lookupkey_t k2, upb_alloc *a) {
4515b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  char *str = upb_malloc(a, k2.str.len + sizeof(uint32_t) + 1);
4516b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (str == NULL) return 0;
4517b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  memcpy(str, &k2.str.len, sizeof(uint32_t));
4518b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  memcpy(str + sizeof(uint32_t), k2.str.str, k2.str.len + 1);
4519b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return (uintptr_t)str;
4520b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4521b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4522b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic uint32_t strhash(upb_tabkey key) {
4523b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  uint32_t len;
4524b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  char *str = upb_tabstr(key, &len);
4525b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return MurmurHash2(str, len, 0);
4526b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4527b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4528b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool streql(upb_tabkey k1, lookupkey_t k2) {
4529b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  uint32_t len;
4530b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  char *str = upb_tabstr(k1, &len);
4531b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return len == k2.str.len && memcmp(str, k2.str.str, len) == 0;
4532b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4533b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4534b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_strtable_init2(upb_strtable *t, upb_ctype_t ctype, upb_alloc *a) {
4535b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return init(&t->t, ctype, 2, a);
4536b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4537b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4538b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_strtable_uninit2(upb_strtable *t, upb_alloc *a) {
4539b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  size_t i;
4540b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for (i = 0; i < upb_table_size(&t->t); i++)
4541b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_free(a, (void*)t->t.entries[i].key);
4542b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  uninit(&t->t, a);
4543b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4544b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4545b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_strtable_resize(upb_strtable *t, size_t size_lg2, upb_alloc *a) {
4546b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_strtable new_table;
4547b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_strtable_iter i;
4548b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4549b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_check_alloc(&t->t, a);
4550b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4551b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!init(&new_table.t, t->t.ctype, size_lg2, a))
4552b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
4553b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_strtable_begin(&i, t);
4554b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for ( ; !upb_strtable_done(&i); upb_strtable_next(&i)) {
4555b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_strtable_insert3(
4556b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        &new_table,
4557b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_strtable_iter_key(&i),
4558b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_strtable_iter_keylength(&i),
4559b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_strtable_iter_value(&i),
4560b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        a);
4561b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
4562b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_strtable_uninit2(t, a);
4563b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  *t = new_table;
4564b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
4565b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4566b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4567b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_strtable_insert3(upb_strtable *t, const char *k, size_t len,
4568b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                          upb_value v, upb_alloc *a) {
4569b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  lookupkey_t key;
4570b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_tabkey tabkey;
4571b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  uint32_t hash;
4572b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4573b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_check_alloc(&t->t, a);
4574b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4575b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (isfull(&t->t)) {
4576b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Need to resize.  New table of double the size, add old elements to it. */
4577b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (!upb_strtable_resize(t, t->t.size_lg2 + 1, a)) {
4578b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return false;
4579b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
4580b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
4581b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4582b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  key = strkey2(k, len);
4583b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  tabkey = strcopy(key, a);
4584b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (tabkey == 0) return false;
4585b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4586b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  hash = MurmurHash2(key.str.str, key.str.len, 0);
4587b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  insert(&t->t, key, tabkey, v, hash, &strhash, &streql);
4588b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
4589b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4590b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4591b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_strtable_lookup2(const upb_strtable *t, const char *key, size_t len,
4592b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                          upb_value *v) {
4593b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  uint32_t hash = MurmurHash2(key, len, 0);
4594b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return lookup(&t->t, strkey2(key, len), v, hash, &streql);
4595b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4596b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4597b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_strtable_remove3(upb_strtable *t, const char *key, size_t len,
4598b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                         upb_value *val, upb_alloc *alloc) {
4599b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  uint32_t hash = MurmurHash2(key, strlen(key), 0);
4600b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_tabkey tabkey;
4601b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (rm(&t->t, strkey2(key, len), val, &tabkey, hash, &streql)) {
4602b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_free(alloc, (void*)tabkey);
4603b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return true;
4604b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
4605b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
4606b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
4607b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4608b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4609b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Iteration */
4610b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4611b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic const upb_tabent *str_tabent(const upb_strtable_iter *i) {
4612b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return &i->t->t.entries[i->index];
4613b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4614b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4615b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_strtable_begin(upb_strtable_iter *i, const upb_strtable *t) {
4616b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  i->t = t;
4617b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  i->index = begin(&t->t);
4618b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4619b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4620b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_strtable_next(upb_strtable_iter *i) {
4621b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  i->index = next(&i->t->t, i->index);
4622b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4623b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4624b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_strtable_done(const upb_strtable_iter *i) {
4625b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return i->index >= upb_table_size(&i->t->t) ||
4626b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer         upb_tabent_isempty(str_tabent(i));
4627b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4628b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4629b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst char *upb_strtable_iter_key(const upb_strtable_iter *i) {
4630b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(!upb_strtable_done(i));
4631b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_tabstr(str_tabent(i)->key, NULL);
4632b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4633b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4634b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammersize_t upb_strtable_iter_keylength(const upb_strtable_iter *i) {
4635b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  uint32_t len;
4636b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(!upb_strtable_done(i));
4637b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_tabstr(str_tabent(i)->key, &len);
4638b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return len;
4639b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4640b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4641b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerupb_value upb_strtable_iter_value(const upb_strtable_iter *i) {
4642b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(!upb_strtable_done(i));
4643b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return _upb_value_val(str_tabent(i)->val.val, i->t->t.ctype);
4644b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4645b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4646b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_strtable_iter_setdone(upb_strtable_iter *i) {
4647b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  i->index = SIZE_MAX;
4648b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4649b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4650b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_strtable_iter_isequal(const upb_strtable_iter *i1,
4651b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                               const upb_strtable_iter *i2) {
4652b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upb_strtable_done(i1) && upb_strtable_done(i2))
4653b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return true;
4654b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return i1->t == i2->t && i1->index == i2->index;
4655b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4656b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4657b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4658b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* upb_inttable ***************************************************************/
4659b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4660b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* For inttables we use a hybrid structure where small keys are kept in an
4661b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * array and large keys are put in the hash table. */
4662b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4663b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic uint32_t inthash(upb_tabkey key) { return upb_inthash(key); }
4664b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4665b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool inteql(upb_tabkey k1, lookupkey_t k2) {
4666b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return k1 == k2.num;
4667b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4668b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4669b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic upb_tabval *mutable_array(upb_inttable *t) {
4670b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return (upb_tabval*)t->array;
4671b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4672b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4673b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic upb_tabval *inttable_val(upb_inttable *t, uintptr_t key) {
4674b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (key < t->array_size) {
4675b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return upb_arrhas(t->array[key]) ? &(mutable_array(t)[key]) : NULL;
4676b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
4677b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_tabent *e =
4678b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        findentry_mutable(&t->t, intkey(key), upb_inthash(key), &inteql);
4679b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return e ? &e->val : NULL;
4680b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
4681b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4682b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4683b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic const upb_tabval *inttable_val_const(const upb_inttable *t,
4684b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                            uintptr_t key) {
4685b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return inttable_val((upb_inttable*)t, key);
4686b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4687b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4688b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammersize_t upb_inttable_count(const upb_inttable *t) {
4689b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return t->t.count + t->array_count;
4690b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4691b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4692b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void check(upb_inttable *t) {
4693b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(t);
4694b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#if defined(UPB_DEBUG_TABLE) && !defined(NDEBUG)
4695b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {
4696b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* This check is very expensive (makes inserts/deletes O(N)). */
4697b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    size_t count = 0;
4698b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_inttable_iter i;
4699b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_inttable_begin(&i, t);
4700b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    for(; !upb_inttable_done(&i); upb_inttable_next(&i), count++) {
4701b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      assert(upb_inttable_lookup(t, upb_inttable_iter_key(&i), NULL));
4702b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
4703b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    assert(count == upb_inttable_count(t));
4704b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
4705b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#endif
4706b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4707b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4708b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_inttable_sizedinit(upb_inttable *t, upb_ctype_t ctype,
4709b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                            size_t asize, int hsize_lg2, upb_alloc *a) {
4710b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  size_t array_bytes;
4711b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4712b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!init(&t->t, ctype, hsize_lg2, a)) return false;
4713b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Always make the array part at least 1 long, so that we know key 0
4714b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * won't be in the hash part, which simplifies things. */
4715b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  t->array_size = UPB_MAX(1, asize);
4716b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  t->array_count = 0;
4717b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  array_bytes = t->array_size * sizeof(upb_value);
4718b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  t->array = upb_malloc(a, array_bytes);
4719b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!t->array) {
4720b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    uninit(&t->t, a);
4721b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
4722b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
4723b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  memset(mutable_array(t), 0xff, array_bytes);
4724b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  check(t);
4725b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
4726b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4727b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4728b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_inttable_init2(upb_inttable *t, upb_ctype_t ctype, upb_alloc *a) {
4729b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_inttable_sizedinit(t, ctype, 0, 4, a);
4730b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4731b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4732b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_inttable_uninit2(upb_inttable *t, upb_alloc *a) {
4733b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  uninit(&t->t, a);
4734b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_free(a, mutable_array(t));
4735b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4736b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4737b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_inttable_insert2(upb_inttable *t, uintptr_t key, upb_value val,
4738b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                          upb_alloc *a) {
4739b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_tabval tabval;
4740b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  tabval.val = val.val;
4741b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(tabval);
4742b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(upb_arrhas(tabval));  /* This will reject (uint64_t)-1.  Fix this. */
4743b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4744b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_check_alloc(&t->t, a);
4745b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4746b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (key < t->array_size) {
4747b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    assert(!upb_arrhas(t->array[key]));
4748b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    t->array_count++;
4749b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    mutable_array(t)[key].val = val.val;
4750b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
4751b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (isfull(&t->t)) {
4752b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      /* Need to resize the hash part, but we re-use the array part. */
4753b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      size_t i;
4754b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_table new_table;
4755b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4756b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (!init(&new_table, t->t.ctype, t->t.size_lg2 + 1, a)) {
4757b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        return false;
4758b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
4759b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4760b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      for (i = begin(&t->t); i < upb_table_size(&t->t); i = next(&t->t, i)) {
4761b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        const upb_tabent *e = &t->t.entries[i];
4762b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        uint32_t hash;
4763b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_value v;
4764b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4765b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        _upb_value_setval(&v, e->val.val, t->t.ctype);
4766b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        hash = upb_inthash(e->key);
4767b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        insert(&new_table, intkey(e->key), e->key, v, hash, &inthash, &inteql);
4768b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
4769b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4770b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      assert(t->t.count == new_table.count);
4771b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4772b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      uninit(&t->t, a);
4773b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      t->t = new_table;
4774b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
4775b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    insert(&t->t, intkey(key), key, val, upb_inthash(key), &inthash, &inteql);
4776b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
4777b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  check(t);
4778b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
4779b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4780b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4781b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_inttable_lookup(const upb_inttable *t, uintptr_t key, upb_value *v) {
4782b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const upb_tabval *table_v = inttable_val_const(t, key);
4783b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!table_v) return false;
4784b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (v) _upb_value_setval(v, table_v->val, t->t.ctype);
4785b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
4786b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4787b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4788b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_inttable_replace(upb_inttable *t, uintptr_t key, upb_value val) {
4789b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_tabval *table_v = inttable_val(t, key);
4790b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!table_v) return false;
4791b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  table_v->val = val.val;
4792b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
4793b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4794b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4795b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_inttable_remove(upb_inttable *t, uintptr_t key, upb_value *val) {
4796b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bool success;
4797b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (key < t->array_size) {
4798b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (upb_arrhas(t->array[key])) {
4799b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_tabval empty = UPB_TABVALUE_EMPTY_INIT;
4800b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      t->array_count--;
4801b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (val) {
4802b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        _upb_value_setval(val, t->array[key].val, t->t.ctype);
4803b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
4804b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      mutable_array(t)[key] = empty;
4805b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      success = true;
4806b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    } else {
4807b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      success = false;
4808b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
4809b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
4810b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_tabkey removed;
4811b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    uint32_t hash = upb_inthash(key);
4812b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    success = rm(&t->t, intkey(key), val, &removed, hash, &inteql);
4813b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
4814b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  check(t);
4815b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return success;
4816b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4817b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4818b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_inttable_push2(upb_inttable *t, upb_value val, upb_alloc *a) {
4819b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_check_alloc(&t->t, a);
4820b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_inttable_insert2(t, upb_inttable_count(t), val, a);
4821b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4822b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4823b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerupb_value upb_inttable_pop(upb_inttable *t) {
4824b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_value val;
4825b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bool ok = upb_inttable_remove(t, upb_inttable_count(t) - 1, &val);
4826b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_ASSERT_VAR(ok, ok);
4827b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return val;
4828b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4829b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4830b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_inttable_insertptr2(upb_inttable *t, const void *key, upb_value val,
4831b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                             upb_alloc *a) {
4832b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_check_alloc(&t->t, a);
4833b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_inttable_insert2(t, (uintptr_t)key, val, a);
4834b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4835b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4836b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_inttable_lookupptr(const upb_inttable *t, const void *key,
4837b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                            upb_value *v) {
4838b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_inttable_lookup(t, (uintptr_t)key, v);
4839b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4840b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4841b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_inttable_removeptr(upb_inttable *t, const void *key, upb_value *val) {
4842b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_inttable_remove(t, (uintptr_t)key, val);
4843b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4844b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4845b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_inttable_compact2(upb_inttable *t, upb_alloc *a) {
4846b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* A power-of-two histogram of the table keys. */
4847b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  size_t counts[UPB_MAXARRSIZE + 1] = {0};
4848b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4849b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* The max key in each bucket. */
4850b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  uintptr_t max[UPB_MAXARRSIZE + 1] = {0};
4851b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4852b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_iter i;
4853b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  size_t arr_count;
4854b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  int size_lg2;
4855b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable new_t;
4856b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4857b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_check_alloc(&t->t, a);
4858b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4859b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_begin(&i, t);
4860b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for (; !upb_inttable_done(&i); upb_inttable_next(&i)) {
4861b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    uintptr_t key = upb_inttable_iter_key(&i);
4862b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    int bucket = log2ceil(key);
4863b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    max[bucket] = UPB_MAX(max[bucket], key);
4864b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    counts[bucket]++;
4865b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
4866b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4867b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Find the largest power of two that satisfies the MIN_DENSITY
4868b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * definition (while actually having some keys). */
4869b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  arr_count = upb_inttable_count(t);
4870b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4871b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for (size_lg2 = ARRAY_SIZE(counts) - 1; size_lg2 > 0; size_lg2--) {
4872b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (counts[size_lg2] == 0) {
4873b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      /* We can halve again without losing any entries. */
4874b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      continue;
4875b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    } else if (arr_count >= (1 << size_lg2) * MIN_DENSITY) {
4876b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
4877b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
4878b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4879b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    arr_count -= counts[size_lg2];
4880b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
4881b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4882b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(arr_count <= upb_inttable_count(t));
4883b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4884b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {
4885b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Insert all elements into new, perfectly-sized table. */
4886b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    size_t arr_size = max[size_lg2] + 1;  /* +1 so arr[max] will fit. */
4887b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    size_t hash_count = upb_inttable_count(t) - arr_count;
4888b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    size_t hash_size = hash_count ? (hash_count / MAX_LOAD) + 1 : 0;
4889b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    size_t hashsize_lg2 = log2ceil(hash_size);
4890b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4891b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_inttable_sizedinit(&new_t, t->t.ctype, arr_size, hashsize_lg2, a);
4892b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_inttable_begin(&i, t);
4893b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    for (; !upb_inttable_done(&i); upb_inttable_next(&i)) {
4894b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      uintptr_t k = upb_inttable_iter_key(&i);
4895b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_inttable_insert2(&new_t, k, upb_inttable_iter_value(&i), a);
4896b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
4897b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    assert(new_t.array_size == arr_size);
4898b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    assert(new_t.t.size_lg2 == hashsize_lg2);
4899b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
4900b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_uninit2(t, a);
4901b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  *t = new_t;
4902b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4903b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4904b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Iteration. */
4905b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4906b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic const upb_tabent *int_tabent(const upb_inttable_iter *i) {
4907b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(!i->array_part);
4908b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return &i->t->t.entries[i->index];
4909b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4910b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4911b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic upb_tabval int_arrent(const upb_inttable_iter *i) {
4912b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(i->array_part);
4913b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return i->t->array[i->index];
4914b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4915b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4916b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_inttable_begin(upb_inttable_iter *i, const upb_inttable *t) {
4917b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  i->t = t;
4918b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  i->index = -1;
4919b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  i->array_part = true;
4920b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_next(i);
4921b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4922b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4923b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_inttable_next(upb_inttable_iter *iter) {
4924b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const upb_inttable *t = iter->t;
4925b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (iter->array_part) {
4926b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    while (++iter->index < t->array_size) {
4927b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (upb_arrhas(int_arrent(iter))) {
4928b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        return;
4929b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
4930b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
4931b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    iter->array_part = false;
4932b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    iter->index = begin(&t->t);
4933b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
4934b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    iter->index = next(&t->t, iter->index);
4935b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
4936b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4937b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4938b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_inttable_done(const upb_inttable_iter *i) {
4939b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (i->array_part) {
4940b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return i->index >= i->t->array_size ||
4941b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer           !upb_arrhas(int_arrent(i));
4942b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
4943b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return i->index >= upb_table_size(&i->t->t) ||
4944b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer           upb_tabent_isempty(int_tabent(i));
4945b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
4946b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4947b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4948b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammeruintptr_t upb_inttable_iter_key(const upb_inttable_iter *i) {
4949b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(!upb_inttable_done(i));
4950b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return i->array_part ? i->index : int_tabent(i)->key;
4951b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4952b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4953b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerupb_value upb_inttable_iter_value(const upb_inttable_iter *i) {
4954b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(!upb_inttable_done(i));
4955b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return _upb_value_val(
4956b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      i->array_part ? i->t->array[i->index].val : int_tabent(i)->val.val,
4957b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      i->t->t.ctype);
4958b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4959b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4960b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_inttable_iter_setdone(upb_inttable_iter *i) {
4961b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  i->index = SIZE_MAX;
4962b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  i->array_part = false;
4963b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4964b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4965b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_inttable_iter_isequal(const upb_inttable_iter *i1,
4966b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                          const upb_inttable_iter *i2) {
4967b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upb_inttable_done(i1) && upb_inttable_done(i2))
4968b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return true;
4969b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return i1->t == i2->t && i1->index == i2->index &&
4970b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer         i1->array_part == i2->array_part;
4971b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
4972b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4973b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#ifdef UPB_UNALIGNED_READS_OK
4974b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* -----------------------------------------------------------------------------
4975b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * MurmurHash2, by Austin Appleby (released as public domain).
4976b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Reformatted and C99-ified by Joshua Haberman.
4977b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Note - This code makes a few assumptions about how your machine behaves -
4978b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *   1. We can read a 4-byte value from any address without crashing
4979b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *   2. sizeof(int) == 4 (in upb this limitation is removed by using uint32_t
4980b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * And it has a few limitations -
4981b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *   1. It will not work incrementally.
4982b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *   2. It will not produce the same results on little-endian and big-endian
4983b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *      machines. */
4984b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammeruint32_t MurmurHash2(const void *key, size_t len, uint32_t seed) {
4985b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* 'm' and 'r' are mixing constants generated offline.
4986b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * They're not really 'magic', they just happen to work well. */
4987b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const uint32_t m = 0x5bd1e995;
4988b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const int32_t r = 24;
4989b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4990b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Initialize the hash to a 'random' value */
4991b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  uint32_t h = seed ^ len;
4992b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4993b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Mix 4 bytes at a time into the hash */
4994b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const uint8_t * data = (const uint8_t *)key;
4995b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  while(len >= 4) {
4996b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    uint32_t k = *(uint32_t *)data;
4997b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
4998b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    k *= m;
4999b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    k ^= k >> r;
5000b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    k *= m;
5001b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5002b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    h *= m;
5003b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    h ^= k;
5004b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5005b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    data += 4;
5006b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    len -= 4;
5007b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
5008b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5009b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Handle the last few bytes of the input array */
5010b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  switch(len) {
5011b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case 3: h ^= data[2] << 16;
5012b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case 2: h ^= data[1] << 8;
5013b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case 1: h ^= data[0]; h *= m;
5014b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  };
5015b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5016b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Do a few final mixes of the hash to ensure the last few
5017b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * bytes are well-incorporated. */
5018b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  h ^= h >> 13;
5019b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  h *= m;
5020b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  h ^= h >> 15;
5021b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5022b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return h;
5023b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
5024b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5025b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#else /* !UPB_UNALIGNED_READS_OK */
5026b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5027b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* -----------------------------------------------------------------------------
5028b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * MurmurHashAligned2, by Austin Appleby
5029b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Same algorithm as MurmurHash2, but only does aligned reads - should be safer
5030b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * on certain platforms.
5031b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Performance will be lower than MurmurHash2 */
5032b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5033b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#define MIX(h,k,m) { k *= m; k ^= k >> r; k *= m; h *= m; h ^= k; }
5034b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5035b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammeruint32_t MurmurHash2(const void * key, size_t len, uint32_t seed) {
5036b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const uint32_t m = 0x5bd1e995;
5037b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const int32_t r = 24;
5038b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const uint8_t * data = (const uint8_t *)key;
5039b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  uint32_t h = seed ^ len;
5040b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  uint8_t align = (uintptr_t)data & 3;
5041b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5042b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if(align && (len >= 4)) {
5043b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Pre-load the temp registers */
5044b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    uint32_t t = 0, d = 0;
5045b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    int32_t sl;
5046b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    int32_t sr;
5047b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5048b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    switch(align) {
5049b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case 1: t |= data[2] << 16;
5050b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case 2: t |= data[1] << 8;
5051b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case 3: t |= data[0];
5052b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
5053b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5054b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    t <<= (8 * align);
5055b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5056b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    data += 4-align;
5057b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    len -= 4-align;
5058b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5059b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    sl = 8 * (4-align);
5060b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    sr = 8 * align;
5061b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5062b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Mix */
5063b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5064b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    while(len >= 4) {
5065b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      uint32_t k;
5066b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5067b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      d = *(uint32_t *)data;
5068b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      t = (t >> sr) | (d << sl);
5069b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5070b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      k = t;
5071b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5072b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      MIX(h,k,m);
5073b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5074b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      t = d;
5075b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5076b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      data += 4;
5077b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      len -= 4;
5078b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
5079b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5080b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Handle leftover data in temp registers */
5081b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5082b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    d = 0;
5083b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5084b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if(len >= align) {
5085b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      uint32_t k;
5086b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5087b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      switch(align) {
5088b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        case 3: d |= data[2] << 16;
5089b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        case 2: d |= data[1] << 8;
5090b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        case 1: d |= data[0];
5091b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
5092b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5093b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      k = (t >> sr) | (d << sl);
5094b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      MIX(h,k,m);
5095b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5096b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      data += align;
5097b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      len -= align;
5098b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5099b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      /* ----------
5100b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer       * Handle tail bytes */
5101b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5102b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      switch(len) {
5103b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        case 3: h ^= data[2] << 16;
5104b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        case 2: h ^= data[1] << 8;
5105b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        case 1: h ^= data[0]; h *= m;
5106b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      };
5107b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    } else {
5108b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      switch(len) {
5109b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        case 3: d |= data[2] << 16;
5110b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        case 2: d |= data[1] << 8;
5111b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        case 1: d |= data[0];
5112b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        case 0: h ^= (t >> sr) | (d << sl); h *= m;
5113b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
5114b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
5115b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5116b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    h ^= h >> 13;
5117b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    h *= m;
5118b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    h ^= h >> 15;
5119b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5120b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return h;
5121b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
5122b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    while(len >= 4) {
5123b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      uint32_t k = *(uint32_t *)data;
5124b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5125b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      MIX(h,k,m);
5126b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5127b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      data += 4;
5128b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      len -= 4;
5129b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
5130b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5131b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* ----------
5132b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * Handle tail bytes */
5133b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5134b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    switch(len) {
5135b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case 3: h ^= data[2] << 16;
5136b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case 2: h ^= data[1] << 8;
5137b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case 1: h ^= data[0]; h *= m;
5138b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    };
5139b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5140b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    h ^= h >> 13;
5141b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    h *= m;
5142b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    h ^= h >> 15;
5143b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5144b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return h;
5145b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
5146b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
5147b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#undef MIX
5148b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5149b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#endif /* UPB_UNALIGNED_READS_OK */
5150b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5151b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <errno.h>
5152b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <stdarg.h>
5153b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <stddef.h>
5154b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <stdint.h>
5155b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <stdio.h>
5156b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <stdlib.h>
5157b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <string.h>
5158b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5159b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_dumptostderr(void *closure, const upb_status* status) {
5160b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(closure);
5161b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  fprintf(stderr, "%s\n", upb_status_errmsg(status));
5162b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return false;
5163b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
5164b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5165b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Guarantee null-termination and provide ellipsis truncation.
5166b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * It may be tempting to "optimize" this by initializing these final
5167b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * four bytes up-front and then being careful never to overwrite them,
5168b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * this is safer and simpler. */
5169b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void nullz(upb_status *status) {
5170b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const char *ellipsis = "...";
5171b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  size_t len = strlen(ellipsis);
5172b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(sizeof(status->msg) > len);
5173b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  memcpy(status->msg + sizeof(status->msg) - len, ellipsis, len);
5174b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
5175b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5176b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5177b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* upb_upberr *****************************************************************/
5178b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5179b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerupb_errorspace upb_upberr = {"upb error"};
5180b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5181b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_upberr_setoom(upb_status *status) {
5182b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  status->error_space_ = &upb_upberr;
5183b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_status_seterrmsg(status, "Out of memory");
5184b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
5185b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5186b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5187b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* upb_status *****************************************************************/
5188b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5189b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_status_clear(upb_status *status) {
5190b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!status) return;
5191b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  status->ok_ = true;
5192b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  status->code_ = 0;
5193b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  status->msg[0] = '\0';
5194b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
5195b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5196b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_ok(const upb_status *status) { return status->ok_; }
5197b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5198b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerupb_errorspace *upb_status_errspace(const upb_status *status) {
5199b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return status->error_space_;
5200b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
5201b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5202b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerint upb_status_errcode(const upb_status *status) { return status->code_; }
5203b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5204b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst char *upb_status_errmsg(const upb_status *status) { return status->msg; }
5205b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5206b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_status_seterrmsg(upb_status *status, const char *msg) {
5207b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!status) return;
5208b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  status->ok_ = false;
5209b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  strncpy(status->msg, msg, sizeof(status->msg));
5210b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  nullz(status);
5211b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
5212b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5213b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_status_seterrf(upb_status *status, const char *fmt, ...) {
5214b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  va_list args;
5215b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  va_start(args, fmt);
5216b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_status_vseterrf(status, fmt, args);
5217b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  va_end(args);
5218b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
5219b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5220b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_status_vseterrf(upb_status *status, const char *fmt, va_list args) {
5221b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!status) return;
5222b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  status->ok_ = false;
5223b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  _upb_vsnprintf(status->msg, sizeof(status->msg), fmt, args);
5224b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  nullz(status);
5225b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
5226b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5227b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_status_copy(upb_status *to, const upb_status *from) {
5228b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!to) return;
5229b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  *to = *from;
5230b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
5231b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5232b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5233b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* upb_alloc ******************************************************************/
5234b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5235b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void *upb_global_allocfunc(upb_alloc *alloc, void *ptr, size_t oldsize,
5236b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                  size_t size) {
5237b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(alloc);
5238b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(oldsize);
5239b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (size == 0) {
5240b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    free(ptr);
5241b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return NULL;
5242b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
5243b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return realloc(ptr, size);
5244b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
5245b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
5246b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5247b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerupb_alloc upb_alloc_global = {&upb_global_allocfunc};
5248b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5249b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5250b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* upb_arena ******************************************************************/
5251b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5252b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Be conservative and choose 16 in case anyone is using SSE. */
5253b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic const size_t maxalign = 16;
5254b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5255b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic size_t align_up(size_t size) {
5256b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return ((size + maxalign - 1) / maxalign) * maxalign;
5257b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
5258b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5259b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammertypedef struct mem_block {
5260b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  struct mem_block *next;
5261b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  size_t size;
5262b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  size_t used;
5263b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bool owned;
5264b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Data follows. */
5265b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer} mem_block;
5266b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5267b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammertypedef struct cleanup_ent {
5268b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  struct cleanup_ent *next;
5269b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_cleanup_func *cleanup;
5270b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  void *ud;
5271b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer} cleanup_ent;
5272b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5273b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void upb_arena_addblock(upb_arena *a, void *ptr, size_t size,
5274b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                               bool owned) {
5275b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  mem_block *block = ptr;
5276b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5277b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  block->next = a->block_head;
5278b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  block->size = size;
5279b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  block->used = align_up(sizeof(mem_block));
5280b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  block->owned = owned;
5281b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5282b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  a->block_head = block;
5283b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5284b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* TODO(haberman): ASAN poison. */
5285b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
5286b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5287b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5288b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic mem_block *upb_arena_allocblock(upb_arena *a, size_t size) {
5289b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  size_t block_size = UPB_MAX(size, a->next_block_size) + sizeof(mem_block);
5290b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  mem_block *block = upb_malloc(a->block_alloc, block_size);
5291b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5292b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!block) {
5293b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return NULL;
5294b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
5295b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5296b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_arena_addblock(a, block, block_size, true);
5297b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  a->next_block_size = UPB_MIN(block_size * 2, a->max_block_size);
5298b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5299b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return block;
5300b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
5301b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5302b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void *upb_arena_doalloc(upb_alloc *alloc, void *ptr, size_t oldsize,
5303b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                               size_t size) {
5304b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_arena *a = (upb_arena*)alloc;  /* upb_alloc is initial member. */
5305b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  mem_block *block = a->block_head;
5306b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  void *ret;
5307b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5308b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (size == 0) {
5309b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return NULL;  /* We are an arena, don't need individual frees. */
5310b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
5311b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5312b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  size = align_up(size);
5313b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5314b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* TODO(haberman): special-case if this is a realloc of the last alloc? */
5315b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5316b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!block || block->size - block->used < size) {
5317b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Slow path: have to allocate a new block. */
5318b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    block = upb_arena_allocblock(a, size);
5319b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5320b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (!block) {
5321b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return NULL;  /* Out of memory. */
5322b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
5323b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
5324b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5325b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  ret = (char*)block + block->used;
5326b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  block->used += size;
5327b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5328b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (oldsize > 0) {
5329b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    memcpy(ret, ptr, oldsize);  /* Preserve existing data. */
5330b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
5331b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5332b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* TODO(haberman): ASAN unpoison. */
5333b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5334b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  a->bytes_allocated += size;
5335b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return ret;
5336b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
5337b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5338b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Public Arena API ***********************************************************/
5339b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5340b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_arena_init(upb_arena *a) {
5341b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  a->alloc.func = &upb_arena_doalloc;
5342b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  a->block_alloc = &upb_alloc_global;
5343b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  a->bytes_allocated = 0;
5344b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  a->next_block_size = 256;
5345b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  a->max_block_size = 16384;
5346b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  a->cleanup_head = NULL;
5347b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  a->block_head = NULL;
5348b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
5349b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5350b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_arena_init2(upb_arena *a, void *mem, size_t size, upb_alloc *alloc) {
5351b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_arena_init(a);
5352b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5353b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (size > sizeof(mem_block)) {
5354b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_arena_addblock(a, mem, size, false);
5355b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
5356b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5357b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (alloc) {
5358b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    a->block_alloc = alloc;
5359b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
5360b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
5361b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5362b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_arena_uninit(upb_arena *a) {
5363b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  cleanup_ent *ent = a->cleanup_head;
5364b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  mem_block *block = a->block_head;
5365b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5366b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  while (ent) {
5367b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    ent->cleanup(ent->ud);
5368b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    ent = ent->next;
5369b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
5370b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5371b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Must do this after running cleanup functions, because this will delete
5372b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * the memory we store our cleanup entries in! */
5373b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  while (block) {
5374b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    mem_block *next = block->next;
5375b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5376b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (block->owned) {
5377b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_free(a->block_alloc, block);
5378b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
5379b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5380b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    block = next;
5381b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
5382b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
5383b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5384b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_arena_addcleanup(upb_arena *a, upb_cleanup_func *func, void *ud) {
5385b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  cleanup_ent *ent = upb_malloc(&a->alloc, sizeof(cleanup_ent));
5386b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!ent) {
5387b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;  /* Out of memory. */
5388b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
5389b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5390b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  ent->cleanup = func;
5391b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  ent->ud = ud;
5392b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  ent->next = a->cleanup_head;
5393b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  a->cleanup_head = ent;
5394b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5395b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
5396b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
5397b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5398b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammersize_t upb_arena_bytesallocated(const upb_arena *a) {
5399b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return a->bytes_allocated;
5400b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
5401b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5402b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5403b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Standard error functions ***************************************************/
5404b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5405b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool default_err(void *ud, const upb_status *status) {
5406b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(ud);
5407b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(status);
5408b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return false;
5409b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
5410b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5411b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool write_err_to(void *ud, const upb_status *status) {
5412b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_status *copy_to = ud;
5413b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_status_copy(copy_to, status);
5414b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return false;
5415b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
5416b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5417b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5418b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* upb_env ********************************************************************/
5419b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5420b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_env_initonly(upb_env *e) {
5421b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  e->ok_ = true;
5422b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  e->error_func_ = &default_err;
5423b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  e->error_ud_ = NULL;
5424b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
5425b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5426b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_env_init(upb_env *e) {
5427b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_arena_init(&e->arena_);
5428b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_env_initonly(e);
5429b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
5430b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5431b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_env_init2(upb_env *e, void *mem, size_t n, upb_alloc *alloc) {
5432b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_arena_init2(&e->arena_, mem, n, alloc);
5433b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_env_initonly(e);
5434b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
5435b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5436b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_env_uninit(upb_env *e) {
5437b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_arena_uninit(&e->arena_);
5438b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
5439b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5440b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_env_seterrorfunc(upb_env *e, upb_error_func *func, void *ud) {
5441b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  e->error_func_ = func;
5442b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  e->error_ud_ = ud;
5443b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
5444b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5445b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_env_reporterrorsto(upb_env *e, upb_status *s) {
5446b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  e->error_func_ = &write_err_to;
5447b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  e->error_ud_ = s;
5448b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
5449b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5450b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_env_reporterror(upb_env *e, const upb_status *status) {
5451b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  e->ok_ = false;
5452b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return e->error_func_(e->error_ud_, status);
5453b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
5454b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5455b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid *upb_env_malloc(upb_env *e, size_t size) {
5456b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_malloc(&e->arena_.alloc, size);
5457b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
5458b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5459b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid *upb_env_realloc(upb_env *e, void *ptr, size_t oldsize, size_t size) {
5460b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_realloc(&e->arena_.alloc, ptr, oldsize, size);
5461b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
5462b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5463b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_env_free(upb_env *e, void *ptr) {
5464b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_free(&e->arena_.alloc, ptr);
5465b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
5466b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5467b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_env_addcleanup(upb_env *e, upb_cleanup_func *func, void *ud) {
5468b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_arena_addcleanup(&e->arena_, func, ud);
5469b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
5470b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5471b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammersize_t upb_env_bytesallocated(const upb_env *e) {
5472b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_arena_bytesallocated(&e->arena_);
5473b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
5474b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* This file was generated by upbc (the upb compiler) from the input
5475b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * file:
5476b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *
5477b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *     upb/descriptor/descriptor.proto
5478b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *
5479b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Do not edit -- your changes will be discarded when the file is
5480b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * regenerated. */
5481b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5482b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <assert.h>
5483b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5484b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5485b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic const upb_msgdef msgs[22];
5486b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic const upb_fielddef fields[105];
5487b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic const upb_enumdef enums[5];
5488b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic const upb_tabent strentries[236];
5489b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic const upb_tabent intentries[18];
5490b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic const upb_tabval arrays[184];
5491b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5492b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#ifdef UPB_DEBUG_REFS
5493b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic upb_inttable reftables[264];
5494b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#endif
5495b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5496b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic const upb_msgdef msgs[22] = {
5497b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]), false, UPB_SYNTAX_PROTO2, &reftables[0], &reftables[1]),
5498b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]), false, UPB_SYNTAX_PROTO2, &reftables[2], &reftables[3]),
5499b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]), false, UPB_SYNTAX_PROTO2, &reftables[4], &reftables[5]),
5500b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]), false, UPB_SYNTAX_PROTO2, &reftables[6], &reftables[7]),
5501b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]), false, UPB_SYNTAX_PROTO2, &reftables[8], &reftables[9]),
5502b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]), false, UPB_SYNTAX_PROTO2, &reftables[10], &reftables[11]),
5503b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]), false, UPB_SYNTAX_PROTO2, &reftables[12], &reftables[13]),
5504b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]), false, UPB_SYNTAX_PROTO2, &reftables[14], &reftables[15]),
5505b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]), false, UPB_SYNTAX_PROTO2, &reftables[16], &reftables[17]),
5506b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]), false, UPB_SYNTAX_PROTO2, &reftables[18], &reftables[19]),
5507b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]), false, UPB_SYNTAX_PROTO2, &reftables[20], &reftables[21]),
5508b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]), false, UPB_SYNTAX_PROTO2, &reftables[22], &reftables[23]),
5509b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]), false, UPB_SYNTAX_PROTO2, &reftables[24], &reftables[25]),
5510b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]), false, UPB_SYNTAX_PROTO2, &reftables[26], &reftables[27]),
5511b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]), false, UPB_SYNTAX_PROTO2, &reftables[28], &reftables[29]),
5512b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]), false, UPB_SYNTAX_PROTO2, &reftables[30], &reftables[31]),
5513b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]), false, UPB_SYNTAX_PROTO2, &reftables[32], &reftables[33]),
5514b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]), false, UPB_SYNTAX_PROTO2, &reftables[34], &reftables[35]),
5515b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]), false, UPB_SYNTAX_PROTO2, &reftables[36], &reftables[37]),
5516b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]), false, UPB_SYNTAX_PROTO2, &reftables[38], &reftables[39]),
5517b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]), false, UPB_SYNTAX_PROTO2, &reftables[40], &reftables[41]),
5518b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]), false, UPB_SYNTAX_PROTO2, &reftables[42], &reftables[43]),
5519b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer};
5520b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5521b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic const upb_fielddef fields[105] = {
5522b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5523b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5524b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5525b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5526b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5527b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5528b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5529b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5530b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5531b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5532b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5533b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5534b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5535b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5536b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5537b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5538b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5539b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5540b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5541b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5542b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5543b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5544b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5545b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5546b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5547b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5548b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5549b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5550b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5551b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5552b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5553b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5554b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5555b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5556b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5557b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5558b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5559b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5560b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5561b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5562b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5563b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5564b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5565b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5566b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5567b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5568b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5569b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5570b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5571b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5572b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5573b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5574b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5575b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5576b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5577b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5578b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5579b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5580b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5581b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5582b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5583b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5584b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5585b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5586b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5587b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5588b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5589b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5590b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5591b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5592b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5593b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5594b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5595b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5596b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5597b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5598b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5599b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5600b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5601b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5602b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5603b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5604b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5605b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5606b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5607b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5608b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5609b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5610b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5611b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5612b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5613b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5614b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5615b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5616b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5617b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5618b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5619b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5620b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5621b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5622b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5623b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5624b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5625b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5626b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5627b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer};
5628b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5629b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic const upb_enumdef enums[5] = {
5630b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5631b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5632b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5633b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5634b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  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]),
5635b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer};
5636b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5637b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic const upb_tabent strentries[236] = {
5638b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "extension"), UPB_TABVALUE_PTR_INIT(&fields[22]), NULL},
5639b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5640b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\015", "\000", "\000", "\000", "reserved_name"), UPB_TABVALUE_PTR_INIT(&fields[82]), NULL},
5641b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[52]), NULL},
5642b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5643b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5644b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5645b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "field"), UPB_TABVALUE_PTR_INIT(&fields[25]), &strentries[12]},
5646b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\017", "\000", "\000", "\000", "extension_range"), UPB_TABVALUE_PTR_INIT(&fields[24]), &strentries[14]},
5647b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5648b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "nested_type"), UPB_TABVALUE_PTR_INIT(&fields[60]), NULL},
5649b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5650b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\016", "\000", "\000", "\000", "reserved_range"), UPB_TABVALUE_PTR_INIT(&fields[83]), NULL},
5651b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[68]), NULL},
5652b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "oneof_decl"), UPB_TABVALUE_PTR_INIT(&fields[65]), NULL},
5653b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "enum_type"), UPB_TABVALUE_PTR_INIT(&fields[19]), &strentries[13]},
5654b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "start"), UPB_TABVALUE_PTR_INIT(&fields[89]), NULL},
5655b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\003", "\000", "\000", "\000", "end"), UPB_TABVALUE_PTR_INIT(&fields[18]), NULL},
5656b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5657b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5658b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "start"), UPB_TABVALUE_PTR_INIT(&fields[88]), NULL},
5659b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\003", "\000", "\000", "\000", "end"), UPB_TABVALUE_PTR_INIT(&fields[17]), NULL},
5660b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5661b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5662b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5663b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "value"), UPB_TABVALUE_PTR_INIT(&fields[102]), NULL},
5664b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[74]), NULL},
5665b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[49]), &strentries[26]},
5666b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[98]), NULL},
5667b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[13]), NULL},
5668b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "allow_alias"), UPB_TABVALUE_PTR_INIT(&fields[1]), NULL},
5669b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5670b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "number"), UPB_TABVALUE_PTR_INIT(&fields[62]), NULL},
5671b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5672b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[73]), NULL},
5673b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[53]), &strentries[34]},
5674b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[97]), NULL},
5675b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[15]), NULL},
5676b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5677b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5678b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "oneof_index"), UPB_TABVALUE_PTR_INIT(&fields[66]), NULL},
5679b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "label"), UPB_TABVALUE_PTR_INIT(&fields[40]), NULL},
5680b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5681b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[55]), NULL},
5682b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5683b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5684b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5685b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5686b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "number"), UPB_TABVALUE_PTR_INIT(&fields[63]), &strentries[53]},
5687b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5688b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\010", "\000", "\000", "\000", "extendee"), UPB_TABVALUE_PTR_INIT(&fields[21]), NULL},
5689b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "type_name"), UPB_TABVALUE_PTR_INIT(&fields[94]), NULL},
5690b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "json_name"), UPB_TABVALUE_PTR_INIT(&fields[38]), NULL},
5691b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "type"), UPB_TABVALUE_PTR_INIT(&fields[93]), &strentries[50]},
5692b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\015", "\000", "\000", "\000", "default_value"), UPB_TABVALUE_PTR_INIT(&fields[7]), NULL},
5693b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[71]), NULL},
5694b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[99]), NULL},
5695b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5696b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "weak"), UPB_TABVALUE_PTR_INIT(&fields[103]), NULL},
5697b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5698b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5699b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5700b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5701b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "packed"), UPB_TABVALUE_PTR_INIT(&fields[77]), NULL},
5702b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "lazy"), UPB_TABVALUE_PTR_INIT(&fields[41]), NULL},
5703b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5704b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "ctype"), UPB_TABVALUE_PTR_INIT(&fields[6]), NULL},
5705b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5706b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "jstype"), UPB_TABVALUE_PTR_INIT(&fields[39]), NULL},
5707b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[10]), NULL},
5708b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5709b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5710b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "extension"), UPB_TABVALUE_PTR_INIT(&fields[23]), NULL},
5711b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\017", "\000", "\000", "\000", "weak_dependency"), UPB_TABVALUE_PTR_INIT(&fields[104]), NULL},
5712b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5713b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[54]), NULL},
5714b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "service"), UPB_TABVALUE_PTR_INIT(&fields[85]), NULL},
5715b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5716b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "source_code_info"), UPB_TABVALUE_PTR_INIT(&fields[86]), NULL},
5717b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5718b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5719b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "syntax"), UPB_TABVALUE_PTR_INIT(&fields[91]), NULL},
5720b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "dependency"), UPB_TABVALUE_PTR_INIT(&fields[8]), NULL},
5721b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "message_type"), UPB_TABVALUE_PTR_INIT(&fields[47]), NULL},
5722b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "package"), UPB_TABVALUE_PTR_INIT(&fields[76]), NULL},
5723b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[69]), &strentries[86]},
5724b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "enum_type"), UPB_TABVALUE_PTR_INIT(&fields[20]), NULL},
5725b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\021", "\000", "\000", "\000", "public_dependency"), UPB_TABVALUE_PTR_INIT(&fields[80]), &strentries[85]},
5726b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5727b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "file"), UPB_TABVALUE_PTR_INIT(&fields[26]), NULL},
5728b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5729b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5730b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5731b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5732b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\023", "\000", "\000", "\000", "cc_generic_services"), UPB_TABVALUE_PTR_INIT(&fields[3]), NULL},
5733b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "csharp_namespace"), UPB_TABVALUE_PTR_INIT(&fields[5]), NULL},
5734b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5735b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5736b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5737b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5738b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5739b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5740b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5741b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "go_package"), UPB_TABVALUE_PTR_INIT(&fields[27]), NULL},
5742b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "java_package"), UPB_TABVALUE_PTR_INIT(&fields[35]), &strentries[120]},
5743b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5744b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5745b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "java_outer_classname"), UPB_TABVALUE_PTR_INIT(&fields[34]), NULL},
5746b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[95]), NULL},
5747b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5748b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5749b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5750b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\023", "\000", "\000", "\000", "java_multiple_files"), UPB_TABVALUE_PTR_INIT(&fields[33]), &strentries[117]},
5751b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5752b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\025", "\000", "\000", "\000", "java_generic_services"), UPB_TABVALUE_PTR_INIT(&fields[32]), &strentries[118]},
5753b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\035", "\000", "\000", "\000", "java_generate_equals_and_hash"), UPB_TABVALUE_PTR_INIT(&fields[31]), NULL},
5754b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5755b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\037", "\000", "\000", "\000", "javanano_use_deprecated_package"), UPB_TABVALUE_PTR_INIT(&fields[37]), &strentries[123]},
5756b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\023", "\000", "\000", "\000", "py_generic_services"), UPB_TABVALUE_PTR_INIT(&fields[81]), NULL},
5757b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "optimize_for"), UPB_TABVALUE_PTR_INIT(&fields[67]), NULL},
5758b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\026", "\000", "\000", "\000", "java_string_check_utf8"), UPB_TABVALUE_PTR_INIT(&fields[36]), NULL},
5759b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[12]), &strentries[119]},
5760b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\021", "\000", "\000", "\000", "objc_class_prefix"), UPB_TABVALUE_PTR_INIT(&fields[64]), NULL},
5761b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "cc_enable_arenas"), UPB_TABVALUE_PTR_INIT(&fields[2]), NULL},
5762b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\027", "\000", "\000", "\000", "message_set_wire_format"), UPB_TABVALUE_PTR_INIT(&fields[46]), &strentries[128]},
5763b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5764b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5765b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5766b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[96]), NULL},
5767b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[9]), NULL},
5768b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "map_entry"), UPB_TABVALUE_PTR_INIT(&fields[45]), NULL},
5769b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\037", "\000", "\000", "\000", "no_standard_descriptor_accessor"), UPB_TABVALUE_PTR_INIT(&fields[61]), NULL},
5770b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5771b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "client_streaming"), UPB_TABVALUE_PTR_INIT(&fields[4]), NULL},
5772b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "server_streaming"), UPB_TABVALUE_PTR_INIT(&fields[84]), NULL},
5773b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[56]), NULL},
5774b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "input_type"), UPB_TABVALUE_PTR_INIT(&fields[29]), NULL},
5775b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5776b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "output_type"), UPB_TABVALUE_PTR_INIT(&fields[75]), NULL},
5777b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[70]), NULL},
5778b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[100]), NULL},
5779b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[11]), NULL},
5780b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5781b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5782b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5783b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5784b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5785b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[50]), NULL},
5786b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5787b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[72]), &strentries[150]},
5788b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "method"), UPB_TABVALUE_PTR_INIT(&fields[48]), NULL},
5789b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[57]), &strentries[149]},
5790b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[101]), NULL},
5791b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[14]), NULL},
5792b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5793b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5794b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5795b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5796b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\010", "\000", "\000", "\000", "location"), UPB_TABVALUE_PTR_INIT(&fields[44]), NULL},
5797b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5798b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5799b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5800b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5801b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "span"), UPB_TABVALUE_PTR_INIT(&fields[87]), &strentries[167]},
5802b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\031", "\000", "\000", "\000", "leading_detached_comments"), UPB_TABVALUE_PTR_INIT(&fields[43]), &strentries[165]},
5803b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\021", "\000", "\000", "\000", "trailing_comments"), UPB_TABVALUE_PTR_INIT(&fields[92]), NULL},
5804b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "leading_comments"), UPB_TABVALUE_PTR_INIT(&fields[42]), &strentries[164]},
5805b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "path"), UPB_TABVALUE_PTR_INIT(&fields[78]), NULL},
5806b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "double_value"), UPB_TABVALUE_PTR_INIT(&fields[16]), NULL},
5807b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5808b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5809b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[51]), NULL},
5810b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5811b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5812b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5813b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\022", "\000", "\000", "\000", "negative_int_value"), UPB_TABVALUE_PTR_INIT(&fields[59]), NULL},
5814b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\017", "\000", "\000", "\000", "aggregate_value"), UPB_TABVALUE_PTR_INIT(&fields[0]), NULL},
5815b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5816b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5817b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5818b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5819b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\022", "\000", "\000", "\000", "positive_int_value"), UPB_TABVALUE_PTR_INIT(&fields[79]), NULL},
5820b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "identifier_value"), UPB_TABVALUE_PTR_INIT(&fields[28]), NULL},
5821b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "string_value"), UPB_TABVALUE_PTR_INIT(&fields[90]), &strentries[182]},
5822b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5823b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5824b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "is_extension"), UPB_TABVALUE_PTR_INIT(&fields[30]), NULL},
5825b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "name_part"), UPB_TABVALUE_PTR_INIT(&fields[58]), NULL},
5826b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\016", "\000", "\000", "\000", "LABEL_REQUIRED"), UPB_TABVALUE_INT_INIT(2), &strentries[190]},
5827b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5828b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\016", "\000", "\000", "\000", "LABEL_REPEATED"), UPB_TABVALUE_INT_INIT(3), NULL},
5829b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\016", "\000", "\000", "\000", "LABEL_OPTIONAL"), UPB_TABVALUE_INT_INIT(1), NULL},
5830b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "TYPE_FIXED64"), UPB_TABVALUE_INT_INIT(6), NULL},
5831b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5832b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5833b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5834b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5835b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "TYPE_STRING"), UPB_TABVALUE_INT_INIT(9), NULL},
5836b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "TYPE_FLOAT"), UPB_TABVALUE_INT_INIT(2), &strentries[221]},
5837b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "TYPE_DOUBLE"), UPB_TABVALUE_INT_INIT(1), NULL},
5838b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5839b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "TYPE_INT32"), UPB_TABVALUE_INT_INIT(5), NULL},
5840b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\015", "\000", "\000", "\000", "TYPE_SFIXED32"), UPB_TABVALUE_INT_INIT(15), NULL},
5841b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "TYPE_FIXED32"), UPB_TABVALUE_INT_INIT(7), NULL},
5842b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5843b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "TYPE_MESSAGE"), UPB_TABVALUE_INT_INIT(11), &strentries[222]},
5844b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5845b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5846b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "TYPE_INT64"), UPB_TABVALUE_INT_INIT(3), &strentries[219]},
5847b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5848b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5849b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5850b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5851b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "TYPE_ENUM"), UPB_TABVALUE_INT_INIT(14), NULL},
5852b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "TYPE_UINT32"), UPB_TABVALUE_INT_INIT(13), NULL},
5853b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5854b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "TYPE_UINT64"), UPB_TABVALUE_INT_INIT(4), &strentries[218]},
5855b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5856b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\015", "\000", "\000", "\000", "TYPE_SFIXED64"), UPB_TABVALUE_INT_INIT(16), NULL},
5857b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "TYPE_BYTES"), UPB_TABVALUE_INT_INIT(12), NULL},
5858b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "TYPE_SINT64"), UPB_TABVALUE_INT_INIT(18), NULL},
5859b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "TYPE_BOOL"), UPB_TABVALUE_INT_INIT(8), NULL},
5860b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "TYPE_GROUP"), UPB_TABVALUE_INT_INIT(10), NULL},
5861b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "TYPE_SINT32"), UPB_TABVALUE_INT_INIT(17), NULL},
5862b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5863b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "CORD"), UPB_TABVALUE_INT_INIT(1), NULL},
5864b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "STRING"), UPB_TABVALUE_INT_INIT(0), &strentries[225]},
5865b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "STRING_PIECE"), UPB_TABVALUE_INT_INIT(2), NULL},
5866b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5867b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "JS_NORMAL"), UPB_TABVALUE_INT_INIT(0), NULL},
5868b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "JS_NUMBER"), UPB_TABVALUE_INT_INIT(2), NULL},
5869b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "JS_STRING"), UPB_TABVALUE_INT_INIT(1), NULL},
5870b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "CODE_SIZE"), UPB_TABVALUE_INT_INIT(2), NULL},
5871b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "SPEED"), UPB_TABVALUE_INT_INIT(1), &strentries[235]},
5872b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5873b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "LITE_RUNTIME"), UPB_TABVALUE_INT_INIT(3), NULL},
5874b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer};
5875b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5876b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic const upb_tabent intentries[18] = {
5877b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5878b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[98]), NULL},
5879b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5880b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[97]), NULL},
5881b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5882b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[99]), NULL},
5883b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5884b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[95]), NULL},
5885b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5886b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[96]), NULL},
5887b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5888b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NUM(33), UPB_TABVALUE_PTR_INIT(&fields[11]), NULL},
5889b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5890b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[100]), NULL},
5891b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5892b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NUM(33), UPB_TABVALUE_PTR_INIT(&fields[14]), NULL},
5893b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
5894b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[101]), NULL},
5895b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer};
5896b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
5897b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic const upb_tabval arrays[184] = {
5898b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_EMPTY_INIT,
5899b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[52]),
5900b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[25]),
5901b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[60]),
5902b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[19]),
5903b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[24]),
5904b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[22]),
5905b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[68]),
5906b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[65]),
5907b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[83]),
5908b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[82]),
5909b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_EMPTY_INIT,
5910b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[89]),
5911b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[18]),
5912b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_EMPTY_INIT,
5913b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[88]),
5914b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[17]),
5915b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_EMPTY_INIT,
5916b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[49]),
5917b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[102]),
5918b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[74]),
5919b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_EMPTY_INIT,
5920b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_EMPTY_INIT,
5921b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[1]),
5922b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[13]),
5923b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_EMPTY_INIT,
5924b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[53]),
5925b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[62]),
5926b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[73]),
5927b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_EMPTY_INIT,
5928b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[15]),
5929b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_EMPTY_INIT,
5930b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[55]),
5931b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[21]),
5932b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[63]),
5933b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[40]),
5934b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[93]),
5935b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[94]),
5936b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[7]),
5937b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[71]),
5938b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[66]),
5939b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[38]),
5940b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_EMPTY_INIT,
5941b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[6]),
5942b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[77]),
5943b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[10]),
5944b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_EMPTY_INIT,
5945b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[41]),
5946b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[39]),
5947b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_EMPTY_INIT,
5948b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_EMPTY_INIT,
5949b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_EMPTY_INIT,
5950b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[103]),
5951b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_EMPTY_INIT,
5952b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[54]),
5953b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[76]),
5954b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[8]),
5955b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[47]),
5956b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[20]),
5957b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[85]),
5958b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[23]),
5959b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[69]),
5960b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[86]),
5961b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[80]),
5962b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[104]),
5963b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[91]),
5964b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_EMPTY_INIT,
5965b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[26]),
5966b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_EMPTY_INIT,
5967b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[35]),
5968b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_EMPTY_INIT,
5969b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_EMPTY_INIT,
5970b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_EMPTY_INIT,
5971b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_EMPTY_INIT,
5972b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_EMPTY_INIT,
5973b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_EMPTY_INIT,
5974b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[34]),
5975b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[67]),
5976b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[33]),
5977b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[27]),
5978b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_EMPTY_INIT,
5979b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_EMPTY_INIT,
5980b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_EMPTY_INIT,
5981b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_EMPTY_INIT,
5982b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[3]),
5983b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[32]),
5984b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[81]),
5985b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_EMPTY_INIT,
5986b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[31]),
5987b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_EMPTY_INIT,
5988b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_EMPTY_INIT,
5989b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[12]),
5990b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_EMPTY_INIT,
5991b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_EMPTY_INIT,
5992b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_EMPTY_INIT,
5993b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[36]),
5994b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_EMPTY_INIT,
5995b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_EMPTY_INIT,
5996b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_EMPTY_INIT,
5997b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[2]),
5998b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_EMPTY_INIT,
5999b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_EMPTY_INIT,
6000b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_EMPTY_INIT,
6001b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_EMPTY_INIT,
6002b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[64]),
6003b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[5]),
6004b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[37]),
6005b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_EMPTY_INIT,
6006b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[46]),
6007b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[61]),
6008b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[9]),
6009b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_EMPTY_INIT,
6010b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_EMPTY_INIT,
6011b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_EMPTY_INIT,
6012b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[45]),
6013b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_EMPTY_INIT,
6014b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[56]),
6015b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[29]),
6016b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[75]),
6017b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[70]),
6018b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[4]),
6019b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[84]),
6020b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_EMPTY_INIT,
6021b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_EMPTY_INIT,
6022b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[50]),
6023b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_EMPTY_INIT,
6024b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[57]),
6025b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[48]),
6026b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[72]),
6027b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_EMPTY_INIT,
6028b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_EMPTY_INIT,
6029b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[44]),
6030b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_EMPTY_INIT,
6031b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[78]),
6032b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[87]),
6033b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[42]),
6034b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[92]),
6035b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_EMPTY_INIT,
6036b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[43]),
6037b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_EMPTY_INIT,
6038b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_EMPTY_INIT,
6039b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[51]),
6040b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[28]),
6041b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[79]),
6042b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[59]),
6043b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[16]),
6044b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[90]),
6045b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[0]),
6046b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_EMPTY_INIT,
6047b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[58]),
6048b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT(&fields[30]),
6049b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_EMPTY_INIT,
6050b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT("LABEL_OPTIONAL"),
6051b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT("LABEL_REQUIRED"),
6052b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT("LABEL_REPEATED"),
6053b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_EMPTY_INIT,
6054b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT("TYPE_DOUBLE"),
6055b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT("TYPE_FLOAT"),
6056b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT("TYPE_INT64"),
6057b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT("TYPE_UINT64"),
6058b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT("TYPE_INT32"),
6059b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT("TYPE_FIXED64"),
6060b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT("TYPE_FIXED32"),
6061b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT("TYPE_BOOL"),
6062b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT("TYPE_STRING"),
6063b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT("TYPE_GROUP"),
6064b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT("TYPE_MESSAGE"),
6065b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT("TYPE_BYTES"),
6066b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT("TYPE_UINT32"),
6067b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT("TYPE_ENUM"),
6068b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT("TYPE_SFIXED32"),
6069b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT("TYPE_SFIXED64"),
6070b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT("TYPE_SINT32"),
6071b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT("TYPE_SINT64"),
6072b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT("STRING"),
6073b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT("CORD"),
6074b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT("STRING_PIECE"),
6075b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT("JS_NORMAL"),
6076b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT("JS_STRING"),
6077b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT("JS_NUMBER"),
6078b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_EMPTY_INIT,
6079b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT("SPEED"),
6080b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT("CODE_SIZE"),
6081b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_TABVALUE_PTR_INIT("LITE_RUNTIME"),
6082b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer};
6083b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6084b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#ifdef UPB_DEBUG_REFS
6085b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic upb_inttable reftables[264] = {
6086b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6087b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6088b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6089b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6090b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6091b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6092b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6093b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6094b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6095b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6096b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6097b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6098b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6099b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6100b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6101b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6102b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6103b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6104b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6105b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6106b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6107b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6108b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6109b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6110b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6111b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6112b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6113b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6114b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6115b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6116b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6117b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6118b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6119b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6120b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6121b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6122b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6123b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6124b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6125b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6126b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6127b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6128b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6129b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6130b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6131b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6132b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6133b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6134b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6135b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6136b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6137b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6138b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6139b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6140b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6141b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6142b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6143b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6144b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6145b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6146b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6147b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6148b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6149b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6150b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6151b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6152b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6153b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6154b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6155b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6156b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6157b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6158b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6159b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6160b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6161b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6162b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6163b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6164b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6165b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6166b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6167b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6168b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6169b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6170b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6171b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6172b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6173b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6174b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6175b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6176b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6177b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6178b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6179b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6180b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6181b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6182b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6183b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6184b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6185b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6186b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6187b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6188b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6189b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6190b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6191b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6192b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6193b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6194b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6195b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6196b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6197b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6198b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6199b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6200b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6201b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6202b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6203b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6204b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6205b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6206b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6207b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6208b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6209b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6210b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6211b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6212b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6213b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6214b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6215b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6216b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6217b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6218b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6219b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6220b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6221b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6222b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6223b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6224b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6225b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6226b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6227b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6228b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6229b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6230b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6231b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6232b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6233b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6234b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6235b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6236b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6237b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6238b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6239b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6240b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6241b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6242b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6243b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6244b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6245b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6246b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6247b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6248b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6249b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6250b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6251b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6252b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6253b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6254b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6255b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6256b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6257b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6258b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6259b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6260b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6261b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6262b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6263b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6264b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6265b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6266b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6267b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6268b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6269b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6270b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6271b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6272b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6273b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6274b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6275b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6276b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6277b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6278b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6279b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6280b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6281b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6282b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6283b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6284b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6285b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6286b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6287b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6288b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6289b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6290b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6291b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6292b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6293b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6294b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6295b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6296b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6297b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6298b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6299b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6300b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6301b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6302b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6303b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6304b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6305b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6306b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6307b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6308b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6309b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6310b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6311b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6312b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6313b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6314b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6315b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6316b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6317b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6318b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6319b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6320b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6321b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6322b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6323b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6324b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6325b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6326b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6327b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6328b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6329b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6330b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6331b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6332b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6333b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6334b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6335b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6336b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6337b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6338b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6339b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6340b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6341b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6342b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6343b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6344b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6345b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6346b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6347b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6348b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6349b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
6350b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer};
6351b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#endif
6352b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6353b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic const upb_msgdef *refm(const upb_msgdef *m, const void *owner) {
6354b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_msgdef_ref(m, owner);
6355b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return m;
6356b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
6357b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6358b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic const upb_enumdef *refe(const upb_enumdef *e, const void *owner) {
6359b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_enumdef_ref(e, owner);
6360b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return e;
6361b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
6362b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6363b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Public API. */
6364b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_msgdef *upbdefs_google_protobuf_DescriptorProto_get(const void *owner) { return refm(&msgs[0], owner); }
6365b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_msgdef *upbdefs_google_protobuf_DescriptorProto_ExtensionRange_get(const void *owner) { return refm(&msgs[1], owner); }
6366b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_msgdef *upbdefs_google_protobuf_DescriptorProto_ReservedRange_get(const void *owner) { return refm(&msgs[2], owner); }
6367b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_msgdef *upbdefs_google_protobuf_EnumDescriptorProto_get(const void *owner) { return refm(&msgs[3], owner); }
6368b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_msgdef *upbdefs_google_protobuf_EnumOptions_get(const void *owner) { return refm(&msgs[4], owner); }
6369b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_msgdef *upbdefs_google_protobuf_EnumValueDescriptorProto_get(const void *owner) { return refm(&msgs[5], owner); }
6370b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_msgdef *upbdefs_google_protobuf_EnumValueOptions_get(const void *owner) { return refm(&msgs[6], owner); }
6371b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_msgdef *upbdefs_google_protobuf_FieldDescriptorProto_get(const void *owner) { return refm(&msgs[7], owner); }
6372b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_msgdef *upbdefs_google_protobuf_FieldOptions_get(const void *owner) { return refm(&msgs[8], owner); }
6373b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_msgdef *upbdefs_google_protobuf_FileDescriptorProto_get(const void *owner) { return refm(&msgs[9], owner); }
6374b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_msgdef *upbdefs_google_protobuf_FileDescriptorSet_get(const void *owner) { return refm(&msgs[10], owner); }
6375b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_msgdef *upbdefs_google_protobuf_FileOptions_get(const void *owner) { return refm(&msgs[11], owner); }
6376b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_msgdef *upbdefs_google_protobuf_MessageOptions_get(const void *owner) { return refm(&msgs[12], owner); }
6377b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_msgdef *upbdefs_google_protobuf_MethodDescriptorProto_get(const void *owner) { return refm(&msgs[13], owner); }
6378b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_msgdef *upbdefs_google_protobuf_MethodOptions_get(const void *owner) { return refm(&msgs[14], owner); }
6379b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_msgdef *upbdefs_google_protobuf_OneofDescriptorProto_get(const void *owner) { return refm(&msgs[15], owner); }
6380b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_msgdef *upbdefs_google_protobuf_ServiceDescriptorProto_get(const void *owner) { return refm(&msgs[16], owner); }
6381b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_msgdef *upbdefs_google_protobuf_ServiceOptions_get(const void *owner) { return refm(&msgs[17], owner); }
6382b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_msgdef *upbdefs_google_protobuf_SourceCodeInfo_get(const void *owner) { return refm(&msgs[18], owner); }
6383b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_msgdef *upbdefs_google_protobuf_SourceCodeInfo_Location_get(const void *owner) { return refm(&msgs[19], owner); }
6384b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_msgdef *upbdefs_google_protobuf_UninterpretedOption_get(const void *owner) { return refm(&msgs[20], owner); }
6385b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_msgdef *upbdefs_google_protobuf_UninterpretedOption_NamePart_get(const void *owner) { return refm(&msgs[21], owner); }
6386b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6387b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_enumdef *upbdefs_google_protobuf_FieldDescriptorProto_Label_get(const void *owner) { return refe(&enums[0], owner); }
6388b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_enumdef *upbdefs_google_protobuf_FieldDescriptorProto_Type_get(const void *owner) { return refe(&enums[1], owner); }
6389b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_enumdef *upbdefs_google_protobuf_FieldOptions_CType_get(const void *owner) { return refe(&enums[2], owner); }
6390b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_enumdef *upbdefs_google_protobuf_FieldOptions_JSType_get(const void *owner) { return refe(&enums[3], owner); }
6391b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_enumdef *upbdefs_google_protobuf_FileOptions_OptimizeMode_get(const void *owner) { return refe(&enums[4], owner); }
6392b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/*
6393b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** XXX: The routines in this file that consume a string do not currently
6394b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** support having the string span buffers.  In the future, as upb_sink and
6395b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** its buffering/sharing functionality evolve there should be an easy and
6396b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** idiomatic way of correctly handling this case.  For now, we accept this
6397b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** limitation since we currently only parse descriptors from single strings.
6398b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer*/
6399b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6400b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6401b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <errno.h>
6402b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <stdlib.h>
6403b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <string.h>
6404b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6405b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Compares a NULL-terminated string with a non-NULL-terminated string. */
6406b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool upb_streq(const char *str, const char *buf, size_t n) {
6407b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return strlen(str) == n && memcmp(str, buf, n) == 0;
6408b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
6409b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6410b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* We keep a stack of all the messages scopes we are currently in, as well as
6411b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * the top-level file scope.  This is necessary to correctly qualify the
6412b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * definitions that are contained inside.  "name" tracks the name of the
6413b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * message or package (a bare name -- not qualified by any enclosing scopes). */
6414b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammertypedef struct {
6415b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  char *name;
6416b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Index of the first def that is under this scope.  For msgdefs, the
6417b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * msgdef itself is at start-1. */
6418b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  int start;
6419b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer} upb_descreader_frame;
6420b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6421b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* The maximum number of nested declarations that are allowed, ie.
6422b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * message Foo {
6423b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *   message Bar {
6424b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *     message Baz {
6425b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *     }
6426b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *   }
6427b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * }
6428b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *
6429b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * This is a resource limit that affects how big our runtime stack can grow.
6430b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * TODO: make this a runtime-settable property of the Reader instance. */
6431b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#define UPB_MAX_MESSAGE_NESTING 64
6432b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6433b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstruct upb_descreader {
6434b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_sink sink;
6435b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable files;
6436b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_filedef *file;  /* The last file in files. */
6437b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_descreader_frame stack[UPB_MAX_MESSAGE_NESTING];
6438b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  int stack_len;
6439b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6440b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  uint32_t number;
6441b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  char *name;
6442b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bool saw_number;
6443b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bool saw_name;
6444b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6445b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  char *default_string;
6446b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6447b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_fielddef *f;
6448b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer};
6449b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6450b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic char *upb_strndup(const char *buf, size_t n) {
6451b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  char *ret = upb_gmalloc(n + 1);
6452b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!ret) return NULL;
6453b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  memcpy(ret, buf, n);
6454b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  ret[n] = '\0';
6455b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return ret;
6456b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
6457b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6458b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Returns a newly allocated string that joins input strings together, for
6459b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * example:
6460b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *   join("Foo.Bar", "Baz") -> "Foo.Bar.Baz"
6461b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *   join("", "Baz") -> "Baz"
6462b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Caller owns a ref on the returned string. */
6463b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic char *upb_join(const char *base, const char *name) {
6464b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!base || strlen(base) == 0) {
6465b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return upb_gstrdup(name);
6466b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
6467b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    char *ret = upb_gmalloc(strlen(base) + strlen(name) + 2);
6468b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (!ret) {
6469b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return NULL;
6470b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
6471b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    ret[0] = '\0';
6472b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    strcat(ret, base);
6473b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    strcat(ret, ".");
6474b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    strcat(ret, name);
6475b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return ret;
6476b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
6477b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
6478b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6479b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Qualify the defname for all defs starting with offset "start" with "str". */
6480b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool upb_descreader_qualify(upb_filedef *f, char *str, int32_t start) {
6481b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  size_t i;
6482b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for (i = start; i < upb_filedef_defcount(f); i++) {
6483b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_def *def = upb_filedef_mutabledef(f, i);
6484b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    char *name = upb_join(str, upb_def_fullname(def));
6485b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (!name) {
6486b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      /* Need better logic here; at this point we've qualified some names but
6487b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer       * not others. */
6488b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return false;
6489b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
6490b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_def_setfullname(def, name, NULL);
6491b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_gfree(name);
6492b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
6493b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
6494b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
6495b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6496b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6497b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* upb_descreader  ************************************************************/
6498b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6499b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic upb_msgdef *upb_descreader_top(upb_descreader *r) {
6500b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  int index;
6501b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(r->stack_len > 1);
6502b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  index = r->stack[r->stack_len-1].start - 1;
6503b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(index >= 0);
6504b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_downcast_msgdef_mutable(upb_filedef_mutabledef(r->file, index));
6505b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
6506b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6507b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic upb_def *upb_descreader_last(upb_descreader *r) {
6508b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_filedef_mutabledef(r->file, upb_filedef_defcount(r->file) - 1);
6509b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
6510b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6511b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Start/end handlers for FileDescriptorProto and DescriptorProto (the two
6512b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * entities that have names and can contain sub-definitions. */
6513b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_descreader_startcontainer(upb_descreader *r) {
6514b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_descreader_frame *f = &r->stack[r->stack_len++];
6515b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  f->start = upb_filedef_defcount(r->file);
6516b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  f->name = NULL;
6517b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
6518b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6519b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_descreader_endcontainer(upb_descreader *r) {
6520b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_descreader_frame *f = &r->stack[--r->stack_len];
6521b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!upb_descreader_qualify(r->file, f->name, f->start)) {
6522b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
6523b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
6524b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_gfree(f->name);
6525b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  f->name = NULL;
6526b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
6527b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
6528b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6529b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_descreader_setscopename(upb_descreader *r, char *str) {
6530b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_descreader_frame *f = &r->stack[r->stack_len-1];
6531b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_gfree(f->name);
6532b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  f->name = str;
6533b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
6534b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6535b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/** Handlers for google.protobuf.FileDescriptorSet. ***************************/
6536b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6537b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void *fileset_startfile(void *closure, const void *hd) {
6538b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_descreader *r = closure;
6539b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(hd);
6540b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  r->file = upb_filedef_new(&r->files);
6541b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_push(&r->files, upb_value_ptr(r->file));
6542b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return r;
6543b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
6544b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6545b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/** Handlers for google.protobuf.FileDescriptorProto. *************************/
6546b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6547b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool file_start(void *closure, const void *hd) {
6548b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_descreader *r = closure;
6549b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(hd);
6550b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_descreader_startcontainer(r);
6551b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
6552b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
6553b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6554b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool file_end(void *closure, const void *hd, upb_status *status) {
6555b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_descreader *r = closure;
6556b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(hd);
6557b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(status);
6558b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_descreader_endcontainer(r);
6559b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
6560b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6561b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic size_t file_onname(void *closure, const void *hd, const char *buf,
6562b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                          size_t n, const upb_bufhandle *handle) {
6563b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_descreader *r = closure;
6564b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  char *name;
6565b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bool ok;
6566b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(hd);
6567b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(handle);
6568b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6569b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  name = upb_strndup(buf, n);
6570b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* XXX: see comment at the top of the file. */
6571b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  ok = upb_filedef_setname(r->file, name, NULL);
6572b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_gfree(name);
6573b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_ASSERT_VAR(ok, ok);
6574b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return n;
6575b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
6576b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6577b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic size_t file_onpackage(void *closure, const void *hd, const char *buf,
6578b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                             size_t n, const upb_bufhandle *handle) {
6579b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_descreader *r = closure;
6580b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  char *package;
6581b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bool ok;
6582b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(hd);
6583b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(handle);
6584b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6585b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  package = upb_strndup(buf, n);
6586b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* XXX: see comment at the top of the file. */
6587b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_descreader_setscopename(r, package);
6588b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  ok = upb_filedef_setpackage(r->file, package, NULL);
6589b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_ASSERT_VAR(ok, ok);
6590b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return n;
6591b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
6592b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6593b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic size_t file_onsyntax(void *closure, const void *hd, const char *buf,
6594b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                            size_t n, const upb_bufhandle *handle) {
6595b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_descreader *r = closure;
6596b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bool ok;
6597b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(hd);
6598b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(handle);
6599b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* XXX: see comment at the top of the file. */
6600b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upb_streq("proto2", buf, n)) {
6601b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    ok = upb_filedef_setsyntax(r->file, UPB_SYNTAX_PROTO2, NULL);
6602b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else if (upb_streq("proto3", buf, n)) {
6603b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    ok = upb_filedef_setsyntax(r->file, UPB_SYNTAX_PROTO3, NULL);
6604b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
6605b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    ok = false;
6606b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
6607b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6608b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_ASSERT_VAR(ok, ok);
6609b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return n;
6610b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
6611b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6612b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void *file_startmsg(void *closure, const void *hd) {
6613b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_descreader *r = closure;
6614b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_msgdef *m = upb_msgdef_new(&m);
6615b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bool ok = upb_filedef_addmsg(r->file, m, &m, NULL);
6616b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(hd);
6617b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_ASSERT_VAR(ok, ok);
6618b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return r;
6619b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
6620b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6621b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void *file_startenum(void *closure, const void *hd) {
6622b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_descreader *r = closure;
6623b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_enumdef *e = upb_enumdef_new(&e);
6624b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bool ok = upb_filedef_addenum(r->file, e, &e, NULL);
6625b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(hd);
6626b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_ASSERT_VAR(ok, ok);
6627b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return r;
6628b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
6629b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6630b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void *file_startext(void *closure, const void *hd) {
6631b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_descreader *r = closure;
6632b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bool ok;
6633b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  r->f = upb_fielddef_new(r);
6634b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  ok = upb_filedef_addext(r->file, r->f, r, NULL);
6635b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(hd);
6636b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_ASSERT_VAR(ok, ok);
6637b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return r;
6638b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
6639b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6640b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/** Handlers for google.protobuf.EnumValueDescriptorProto. *********************/
6641b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6642b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool enumval_startmsg(void *closure, const void *hd) {
6643b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_descreader *r = closure;
6644b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(hd);
6645b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  r->saw_number = false;
6646b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  r->saw_name = false;
6647b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
6648b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
6649b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6650b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic size_t enumval_onname(void *closure, const void *hd, const char *buf,
6651b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                             size_t n, const upb_bufhandle *handle) {
6652b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_descreader *r = closure;
6653b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(hd);
6654b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(handle);
6655b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* XXX: see comment at the top of the file. */
6656b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_gfree(r->name);
6657b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  r->name = upb_strndup(buf, n);
6658b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  r->saw_name = true;
6659b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return n;
6660b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
6661b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6662b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool enumval_onnumber(void *closure, const void *hd, int32_t val) {
6663b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_descreader *r = closure;
6664b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(hd);
6665b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  r->number = val;
6666b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  r->saw_number = true;
6667b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
6668b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
6669b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6670b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool enumval_endmsg(void *closure, const void *hd, upb_status *status) {
6671b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_descreader *r = closure;
6672b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_enumdef *e;
6673b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(hd);
6674b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6675b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if(!r->saw_number || !r->saw_name) {
6676b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_status_seterrmsg(status, "Enum value missing name or number.");
6677b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
6678b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
6679b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  e = upb_downcast_enumdef_mutable(upb_descreader_last(r));
6680b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_enumdef_addval(e, r->name, r->number, status);
6681b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_gfree(r->name);
6682b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  r->name = NULL;
6683b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
6684b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
6685b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6686b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/** Handlers for google.protobuf.EnumDescriptorProto. *************************/
6687b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6688b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool enum_endmsg(void *closure, const void *hd, upb_status *status) {
6689b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_descreader *r = closure;
6690b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_enumdef *e;
6691b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(hd);
6692b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6693b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  e = upb_downcast_enumdef_mutable(upb_descreader_last(r));
6694b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upb_def_fullname(upb_descreader_last(r)) == NULL) {
6695b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_status_seterrmsg(status, "Enum had no name.");
6696b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
6697b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
6698b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upb_enumdef_numvals(e) == 0) {
6699b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_status_seterrmsg(status, "Enum had no values.");
6700b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
6701b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
6702b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
6703b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
6704b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6705b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic size_t enum_onname(void *closure, const void *hd, const char *buf,
6706b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                          size_t n, const upb_bufhandle *handle) {
6707b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_descreader *r = closure;
6708b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  char *fullname = upb_strndup(buf, n);
6709b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(hd);
6710b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(handle);
6711b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* XXX: see comment at the top of the file. */
6712b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_def_setfullname(upb_descreader_last(r), fullname, NULL);
6713b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_gfree(fullname);
6714b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return n;
6715b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
6716b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6717b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/** Handlers for google.protobuf.FieldDescriptorProto *************************/
6718b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6719b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool field_startmsg(void *closure, const void *hd) {
6720b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_descreader *r = closure;
6721b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(hd);
6722b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(r->f);
6723b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_gfree(r->default_string);
6724b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  r->default_string = NULL;
6725b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6726b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* fielddefs default to packed, but descriptors default to non-packed. */
6727b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_fielddef_setpacked(r->f, false);
6728b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
6729b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
6730b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6731b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Converts the default value in string "str" into "d".  Passes a ref on str.
6732b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Returns true on success. */
6733b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool parse_default(char *str, upb_fielddef *f) {
6734b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bool success = true;
6735b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  char *end;
6736b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  switch (upb_fielddef_type(f)) {
6737b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_INT32: {
6738b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      long val = strtol(str, &end, 0);
6739b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (val > INT32_MAX || val < INT32_MIN || errno == ERANGE || *end)
6740b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        success = false;
6741b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      else
6742b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_fielddef_setdefaultint32(f, val);
6743b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
6744b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
6745b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_INT64: {
6746b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      /* XXX: Need to write our own strtoll, since it's not available in c89. */
6747b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      long long val = strtol(str, &end, 0);
6748b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (val > INT64_MAX || val < INT64_MIN || errno == ERANGE || *end)
6749b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        success = false;
6750b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      else
6751b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_fielddef_setdefaultint64(f, val);
6752b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
6753b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
6754b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_UINT32: {
6755b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      unsigned long val = strtoul(str, &end, 0);
6756b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (val > UINT32_MAX || errno == ERANGE || *end)
6757b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        success = false;
6758b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      else
6759b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_fielddef_setdefaultuint32(f, val);
6760b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
6761b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
6762b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_UINT64: {
6763b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      /* XXX: Need to write our own strtoull, since it's not available in c89. */
6764b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      unsigned long long val = strtoul(str, &end, 0);
6765b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (val > UINT64_MAX || errno == ERANGE || *end)
6766b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        success = false;
6767b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      else
6768b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_fielddef_setdefaultuint64(f, val);
6769b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
6770b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
6771b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_DOUBLE: {
6772b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      double val = strtod(str, &end);
6773b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (errno == ERANGE || *end)
6774b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        success = false;
6775b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      else
6776b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_fielddef_setdefaultdouble(f, val);
6777b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
6778b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
6779b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_FLOAT: {
6780b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      /* XXX: Need to write our own strtof, since it's not available in c89. */
6781b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      float val = strtod(str, &end);
6782b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (errno == ERANGE || *end)
6783b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        success = false;
6784b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      else
6785b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_fielddef_setdefaultfloat(f, val);
6786b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
6787b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
6788b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_BOOL: {
6789b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (strcmp(str, "false") == 0)
6790b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_fielddef_setdefaultbool(f, false);
6791b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      else if (strcmp(str, "true") == 0)
6792b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_fielddef_setdefaultbool(f, true);
6793b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      else
6794b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        success = false;
6795b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
6796b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
6797b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    default: abort();
6798b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
6799b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return success;
6800b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
6801b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6802b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool field_endmsg(void *closure, const void *hd, upb_status *status) {
6803b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_descreader *r = closure;
6804b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_fielddef *f = r->f;
6805b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(hd);
6806b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6807b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* TODO: verify that all required fields were present. */
6808b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(upb_fielddef_number(f) != 0);
6809b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(upb_fielddef_name(f) != NULL);
6810b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert((upb_fielddef_subdefname(f) != NULL) == upb_fielddef_hassubdef(f));
6811b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6812b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (r->default_string) {
6813b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (upb_fielddef_issubmsg(f)) {
6814b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_status_seterrmsg(status, "Submessages cannot have defaults.");
6815b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return false;
6816b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
6817b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (upb_fielddef_isstring(f) || upb_fielddef_type(f) == UPB_TYPE_ENUM) {
6818b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_fielddef_setdefaultcstr(f, r->default_string, NULL);
6819b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    } else {
6820b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (r->default_string && !parse_default(r->default_string, f)) {
6821b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        /* We don't worry too much about giving a great error message since the
6822b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer         * compiler should have ensured this was correct. */
6823b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_status_seterrmsg(status, "Error converting default value.");
6824b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        return false;
6825b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
6826b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
6827b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
6828b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
6829b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
6830b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6831b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool field_onlazy(void *closure, const void *hd, bool val) {
6832b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_descreader *r = closure;
6833b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(hd);
6834b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6835b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_fielddef_setlazy(r->f, val);
6836b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
6837b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
6838b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6839b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool field_onpacked(void *closure, const void *hd, bool val) {
6840b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_descreader *r = closure;
6841b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(hd);
6842b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6843b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_fielddef_setpacked(r->f, val);
6844b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
6845b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
6846b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6847b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool field_ontype(void *closure, const void *hd, int32_t val) {
6848b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_descreader *r = closure;
6849b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(hd);
6850b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6851b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_fielddef_setdescriptortype(r->f, val);
6852b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
6853b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
6854b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6855b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool field_onlabel(void *closure, const void *hd, int32_t val) {
6856b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_descreader *r = closure;
6857b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(hd);
6858b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6859b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_fielddef_setlabel(r->f, val);
6860b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
6861b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
6862b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6863b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool field_onnumber(void *closure, const void *hd, int32_t val) {
6864b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_descreader *r = closure;
6865b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bool ok;
6866b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(hd);
6867b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6868b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  ok = upb_fielddef_setnumber(r->f, val, NULL);
6869b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_ASSERT_VAR(ok, ok);
6870b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
6871b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
6872b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6873b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic size_t field_onname(void *closure, const void *hd, const char *buf,
6874b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                           size_t n, const upb_bufhandle *handle) {
6875b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_descreader *r = closure;
6876b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  char *name = upb_strndup(buf, n);
6877b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(hd);
6878b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(handle);
6879b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6880b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* XXX: see comment at the top of the file. */
6881b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_fielddef_setname(r->f, name, NULL);
6882b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_gfree(name);
6883b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return n;
6884b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
6885b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6886b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic size_t field_ontypename(void *closure, const void *hd, const char *buf,
6887b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                               size_t n, const upb_bufhandle *handle) {
6888b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_descreader *r = closure;
6889b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  char *name = upb_strndup(buf, n);
6890b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(hd);
6891b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(handle);
6892b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6893b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* XXX: see comment at the top of the file. */
6894b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_fielddef_setsubdefname(r->f, name, NULL);
6895b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_gfree(name);
6896b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return n;
6897b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
6898b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6899b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic size_t field_onextendee(void *closure, const void *hd, const char *buf,
6900b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                               size_t n, const upb_bufhandle *handle) {
6901b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_descreader *r = closure;
6902b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  char *name = upb_strndup(buf, n);
6903b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(hd);
6904b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(handle);
6905b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6906b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* XXX: see comment at the top of the file. */
6907b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_fielddef_setcontainingtypename(r->f, name, NULL);
6908b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_gfree(name);
6909b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return n;
6910b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
6911b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6912b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic size_t field_ondefaultval(void *closure, const void *hd, const char *buf,
6913b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                 size_t n, const upb_bufhandle *handle) {
6914b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_descreader *r = closure;
6915b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(hd);
6916b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(handle);
6917b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6918b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Have to convert from string to the correct type, but we might not know the
6919b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * type yet, so we save it as a string until the end of the field.
6920b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * XXX: see comment at the top of the file. */
6921b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_gfree(r->default_string);
6922b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  r->default_string = upb_strndup(buf, n);
6923b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return n;
6924b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
6925b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6926b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/** Handlers for google.protobuf.DescriptorProto ******************************/
6927b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6928b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool msg_start(void *closure, const void *hd) {
6929b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_descreader *r = closure;
6930b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(hd);
6931b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6932b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_descreader_startcontainer(r);
6933b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
6934b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
6935b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6936b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool msg_end(void *closure, const void *hd, upb_status *status) {
6937b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_descreader *r = closure;
6938b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_msgdef *m = upb_descreader_top(r);
6939b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(hd);
6940b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6941b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if(!upb_def_fullname(upb_msgdef_upcast_mutable(m))) {
6942b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_status_seterrmsg(status, "Encountered message with no name.");
6943b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
6944b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
6945b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_descreader_endcontainer(r);
6946b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
6947b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6948b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic size_t msg_name(void *closure, const void *hd, const char *buf,
6949b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                       size_t n, const upb_bufhandle *handle) {
6950b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_descreader *r = closure;
6951b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_msgdef *m = upb_descreader_top(r);
6952b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* XXX: see comment at the top of the file. */
6953b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  char *name = upb_strndup(buf, n);
6954b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(hd);
6955b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(handle);
6956b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6957b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_def_setfullname(upb_msgdef_upcast_mutable(m), name, NULL);
6958b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_descreader_setscopename(r, name);  /* Passes ownership of name. */
6959b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return n;
6960b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
6961b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6962b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void *msg_startmsg(void *closure, const void *hd) {
6963b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_descreader *r = closure;
6964b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_msgdef *m = upb_msgdef_new(&m);
6965b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bool ok = upb_filedef_addmsg(r->file, m, &m, NULL);
6966b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(hd);
6967b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_ASSERT_VAR(ok, ok);
6968b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return r;
6969b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
6970b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6971b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void *msg_startext(void *closure, const void *hd) {
6972b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_descreader *r = closure;
6973b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_fielddef *f = upb_fielddef_new(&f);
6974b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bool ok = upb_filedef_addext(r->file, f, &f, NULL);
6975b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(hd);
6976b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_ASSERT_VAR(ok, ok);
6977b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return r;
6978b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
6979b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6980b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void *msg_startfield(void *closure, const void *hd) {
6981b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_descreader *r = closure;
6982b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  r->f = upb_fielddef_new(&r->f);
6983b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* We can't add the new field to the message until its name/number are
6984b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * filled in. */
6985b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(hd);
6986b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return r;
6987b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
6988b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6989b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool msg_endfield(void *closure, const void *hd) {
6990b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_descreader *r = closure;
6991b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_msgdef *m = upb_descreader_top(r);
6992b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(hd);
6993b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6994b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_msgdef_addfield(m, r->f, &r->f, NULL);
6995b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  r->f = NULL;
6996b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
6997b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
6998b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
6999b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool msg_onmapentry(void *closure, const void *hd, bool mapentry) {
7000b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_descreader *r = closure;
7001b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_msgdef *m = upb_descreader_top(r);
7002b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(hd);
7003b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7004b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_msgdef_setmapentry(m, mapentry);
7005b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  r->f = NULL;
7006b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
7007b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
7008b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7009b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7010b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7011b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/** Code to register handlers *************************************************/
7012b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7013b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#define F(msg, field) upbdefs_google_protobuf_ ## msg ## _f_ ## field(m)
7014b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7015b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void reghandlers(const void *closure, upb_handlers *h) {
7016b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const upb_msgdef *m = upb_handlers_msgdef(h);
7017b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(closure);
7018b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7019b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upbdefs_google_protobuf_FileDescriptorSet_is(m)) {
7020b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_handlers_setstartsubmsg(h, F(FileDescriptorSet, file),
7021b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                &fileset_startfile, NULL);
7022b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else if (upbdefs_google_protobuf_DescriptorProto_is(m)) {
7023b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_handlers_setstartmsg(h, &msg_start, NULL);
7024b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_handlers_setendmsg(h, &msg_end, NULL);
7025b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_handlers_setstring(h, F(DescriptorProto, name), &msg_name, NULL);
7026b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_handlers_setstartsubmsg(h, F(DescriptorProto, extension), &msg_startext,
7027b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                NULL);
7028b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_handlers_setstartsubmsg(h, F(DescriptorProto, nested_type),
7029b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                &msg_startmsg, NULL);
7030b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_handlers_setstartsubmsg(h, F(DescriptorProto, field),
7031b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                &msg_startfield, NULL);
7032b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_handlers_setendsubmsg(h, F(DescriptorProto, field),
7033b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                              &msg_endfield, NULL);
7034b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_handlers_setstartsubmsg(h, F(DescriptorProto, enum_type),
7035b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                &file_startenum, NULL);
7036b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else if (upbdefs_google_protobuf_FileDescriptorProto_is(m)) {
7037b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_handlers_setstartmsg(h, &file_start, NULL);
7038b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_handlers_setendmsg(h, &file_end, NULL);
7039b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_handlers_setstring(h, F(FileDescriptorProto, name), &file_onname,
7040b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                           NULL);
7041b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_handlers_setstring(h, F(FileDescriptorProto, package), &file_onpackage,
7042b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                           NULL);
7043b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_handlers_setstring(h, F(FileDescriptorProto, syntax), &file_onsyntax,
7044b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                           NULL);
7045b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_handlers_setstartsubmsg(h, F(FileDescriptorProto, message_type),
7046b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                &file_startmsg, NULL);
7047b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_handlers_setstartsubmsg(h, F(FileDescriptorProto, enum_type),
7048b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                &file_startenum, NULL);
7049b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_handlers_setstartsubmsg(h, F(FileDescriptorProto, extension),
7050b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                &file_startext, NULL);
7051b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else if (upbdefs_google_protobuf_EnumValueDescriptorProto_is(m)) {
7052b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_handlers_setstartmsg(h, &enumval_startmsg, NULL);
7053b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_handlers_setendmsg(h, &enumval_endmsg, NULL);
7054b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_handlers_setstring(h, F(EnumValueDescriptorProto, name), &enumval_onname, NULL);
7055b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_handlers_setint32(h, F(EnumValueDescriptorProto, number), &enumval_onnumber,
7056b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                          NULL);
7057b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else if (upbdefs_google_protobuf_EnumDescriptorProto_is(m)) {
7058b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_handlers_setendmsg(h, &enum_endmsg, NULL);
7059b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_handlers_setstring(h, F(EnumDescriptorProto, name), &enum_onname, NULL);
7060b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else if (upbdefs_google_protobuf_FieldDescriptorProto_is(m)) {
7061b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_handlers_setstartmsg(h, &field_startmsg, NULL);
7062b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_handlers_setendmsg(h, &field_endmsg, NULL);
7063b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_handlers_setint32(h, F(FieldDescriptorProto, type), &field_ontype,
7064b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                          NULL);
7065b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_handlers_setint32(h, F(FieldDescriptorProto, label), &field_onlabel,
7066b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                          NULL);
7067b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_handlers_setint32(h, F(FieldDescriptorProto, number), &field_onnumber,
7068b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                          NULL);
7069b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_handlers_setstring(h, F(FieldDescriptorProto, name), &field_onname,
7070b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                           NULL);
7071b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_handlers_setstring(h, F(FieldDescriptorProto, type_name),
7072b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                           &field_ontypename, NULL);
7073b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_handlers_setstring(h, F(FieldDescriptorProto, extendee),
7074b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                           &field_onextendee, NULL);
7075b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_handlers_setstring(h, F(FieldDescriptorProto, default_value),
7076b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                           &field_ondefaultval, NULL);
7077b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else if (upbdefs_google_protobuf_FieldOptions_is(m)) {
7078b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_handlers_setbool(h, F(FieldOptions, lazy), &field_onlazy, NULL);
7079b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_handlers_setbool(h, F(FieldOptions, packed), &field_onpacked, NULL);
7080b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else if (upbdefs_google_protobuf_MessageOptions_is(m)) {
7081b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_handlers_setbool(h, F(MessageOptions, map_entry), &msg_onmapentry, NULL);
7082b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
7083b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7084b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(upb_ok(upb_handlers_status(h)));
7085b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
7086b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7087b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#undef F
7088b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7089b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid descreader_cleanup(void *_r) {
7090b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_descreader *r = _r;
7091b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  size_t i;
7092b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7093b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for (i = 0; i < upb_descreader_filecount(r); i++) {
7094b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_filedef_unref(upb_descreader_file(r, i), &r->files);
7095b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
7096b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7097b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_gfree(r->name);
7098b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_uninit(&r->files);
7099b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_gfree(r->default_string);
7100b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  while (r->stack_len > 0) {
7101b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_descreader_frame *f = &r->stack[--r->stack_len];
7102b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_gfree(f->name);
7103b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
7104b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
7105b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7106b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7107b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Public API  ****************************************************************/
7108b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7109b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerupb_descreader *upb_descreader_create(upb_env *e, const upb_handlers *h) {
7110b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_descreader *r = upb_env_malloc(e, sizeof(upb_descreader));
7111b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!r || !upb_env_addcleanup(e, descreader_cleanup, r)) {
7112b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return NULL;
7113b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
7114b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7115b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_init(&r->files, UPB_CTYPE_PTR);
7116b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_sink_reset(upb_descreader_input(r), h, r);
7117b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  r->stack_len = 0;
7118b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  r->name = NULL;
7119b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  r->default_string = NULL;
7120b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7121b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return r;
7122b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
7123b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7124b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammersize_t upb_descreader_filecount(const upb_descreader *r) {
7125b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_inttable_count(&r->files);
7126b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
7127b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7128b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerupb_filedef *upb_descreader_file(const upb_descreader *r, size_t i) {
7129b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_value v;
7130b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upb_inttable_lookup(&r->files, i, &v)) {
7131b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return upb_value_getptr(v);
7132b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
7133b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return NULL;
7134b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
7135b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
7136b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7137b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerupb_sink *upb_descreader_input(upb_descreader *r) {
7138b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return &r->sink;
7139b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
7140b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7141b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_handlers *upb_descreader_newhandlers(const void *owner) {
7142b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const upb_msgdef *m = upbdefs_google_protobuf_FileDescriptorSet_get(&m);
7143b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const upb_handlers *h = upb_handlers_newfrozen(m, owner, reghandlers, NULL);
7144b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_msgdef_unref(m, &m);
7145b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return h;
7146b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
7147b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/*
7148b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** protobuf decoder bytecode compiler
7149b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer**
7150b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** Code to compile a upb::Handlers into bytecode for decoding a protobuf
7151b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** according to that specific schema and destination handlers.
7152b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer**
7153b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** Compiling to bytecode is always the first step.  If we are using the
7154b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** interpreted decoder we leave it as bytecode and interpret that.  If we are
7155b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** using a JIT decoder we use a code generator to turn the bytecode into native
7156b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** code, LLVM IR, etc.
7157b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer**
7158b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** Bytecode definition is in decoder.int.h.
7159b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer*/
7160b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7161b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <stdarg.h>
7162b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7163b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#ifdef UPB_DUMP_BYTECODE
7164b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <stdio.h>
7165b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#endif
7166b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7167b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#define MAXLABEL 5
7168b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#define EMPTYLABEL -1
7169b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7170b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* mgroup *********************************************************************/
7171b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7172b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void freegroup(upb_refcounted *r) {
7173b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  mgroup *g = (mgroup*)r;
7174b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_uninit(&g->methods);
7175b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#ifdef UPB_USE_JIT_X64
7176b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_pbdecoder_freejit(g);
7177b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#endif
7178b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_gfree(g->bytecode);
7179b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_gfree(g);
7180b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
7181b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7182b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void visitgroup(const upb_refcounted *r, upb_refcounted_visit *visit,
7183b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                       void *closure) {
7184b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const mgroup *g = (const mgroup*)r;
7185b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_iter i;
7186b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_begin(&i, &g->methods);
7187b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
7188b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_pbdecodermethod *method = upb_value_getptr(upb_inttable_iter_value(&i));
7189b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    visit(r, upb_pbdecodermethod_upcast(method), closure);
7190b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
7191b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
7192b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7193b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammermgroup *newgroup(const void *owner) {
7194b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  mgroup *g = upb_gmalloc(sizeof(*g));
7195b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  static const struct upb_refcounted_vtbl vtbl = {visitgroup, freegroup};
7196b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_refcounted_init(mgroup_upcast_mutable(g), &vtbl, owner);
7197b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_init(&g->methods, UPB_CTYPE_PTR);
7198b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  g->bytecode = NULL;
7199b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  g->bytecode_end = NULL;
7200b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return g;
7201b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
7202b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7203b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7204b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* upb_pbdecodermethod ********************************************************/
7205b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7206b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void freemethod(upb_refcounted *r) {
7207b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_pbdecodermethod *method = (upb_pbdecodermethod*)r;
7208b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7209b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (method->dest_handlers_) {
7210b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_handlers_unref(method->dest_handlers_, method);
7211b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
7212b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7213b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_uninit(&method->dispatch);
7214b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_gfree(method);
7215b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
7216b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7217b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void visitmethod(const upb_refcounted *r, upb_refcounted_visit *visit,
7218b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                        void *closure) {
7219b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const upb_pbdecodermethod *m = (const upb_pbdecodermethod*)r;
7220b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  visit(r, m->group, closure);
7221b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
7222b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7223b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic upb_pbdecodermethod *newmethod(const upb_handlers *dest_handlers,
7224b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                      mgroup *group) {
7225b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  static const struct upb_refcounted_vtbl vtbl = {visitmethod, freemethod};
7226b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_pbdecodermethod *ret = upb_gmalloc(sizeof(*ret));
7227b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_refcounted_init(upb_pbdecodermethod_upcast_mutable(ret), &vtbl, &ret);
7228b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_byteshandler_init(&ret->input_handler_);
7229b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7230b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* The method references the group and vice-versa, in a circular reference. */
7231b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_ref2(ret, group);
7232b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_ref2(group, ret);
7233b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_insertptr(&group->methods, dest_handlers, upb_value_ptr(ret));
7234b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_pbdecodermethod_unref(ret, &ret);
7235b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7236b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  ret->group = mgroup_upcast_mutable(group);
7237b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  ret->dest_handlers_ = dest_handlers;
7238b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  ret->is_native_ = false;  /* If we JIT, it will update this later. */
7239b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_init(&ret->dispatch, UPB_CTYPE_UINT64);
7240b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7241b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (ret->dest_handlers_) {
7242b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_handlers_ref(ret->dest_handlers_, ret);
7243b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
7244b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return ret;
7245b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
7246b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7247b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_handlers *upb_pbdecodermethod_desthandlers(
7248b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    const upb_pbdecodermethod *m) {
7249b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return m->dest_handlers_;
7250b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
7251b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7252b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_byteshandler *upb_pbdecodermethod_inputhandler(
7253b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    const upb_pbdecodermethod *m) {
7254b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return &m->input_handler_;
7255b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
7256b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7257b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_pbdecodermethod_isnative(const upb_pbdecodermethod *m) {
7258b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return m->is_native_;
7259b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
7260b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7261b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_pbdecodermethod *upb_pbdecodermethod_new(
7262b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    const upb_pbdecodermethodopts *opts, const void *owner) {
7263b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const upb_pbdecodermethod *ret;
7264b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_pbcodecache cache;
7265b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7266b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_pbcodecache_init(&cache);
7267b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  ret = upb_pbcodecache_getdecodermethod(&cache, opts);
7268b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_pbdecodermethod_ref(ret, owner);
7269b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_pbcodecache_uninit(&cache);
7270b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return ret;
7271b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
7272b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7273b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7274b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* bytecode compiler **********************************************************/
7275b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7276b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Data used only at compilation time. */
7277b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammertypedef struct {
7278b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  mgroup *group;
7279b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7280b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  uint32_t *pc;
7281b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  int fwd_labels[MAXLABEL];
7282b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  int back_labels[MAXLABEL];
7283b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7284b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* For fields marked "lazy", parse them lazily or eagerly? */
7285b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bool lazy;
7286b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer} compiler;
7287b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7288b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic compiler *newcompiler(mgroup *group, bool lazy) {
7289b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  compiler *ret = upb_gmalloc(sizeof(*ret));
7290b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  int i;
7291b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7292b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  ret->group = group;
7293b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  ret->lazy = lazy;
7294b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for (i = 0; i < MAXLABEL; i++) {
7295b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    ret->fwd_labels[i] = EMPTYLABEL;
7296b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    ret->back_labels[i] = EMPTYLABEL;
7297b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
7298b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return ret;
7299b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
7300b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7301b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void freecompiler(compiler *c) {
7302b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_gfree(c);
7303b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
7304b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7305b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst size_t ptr_words = sizeof(void*) / sizeof(uint32_t);
7306b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7307b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* How many words an instruction is. */
7308b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic int instruction_len(uint32_t instr) {
7309b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  switch (getop(instr)) {
7310b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_SETDISPATCH: return 1 + ptr_words;
7311b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_TAGN: return 3;
7312b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_SETBIGGROUPNUM: return 2;
7313b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    default: return 1;
7314b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
7315b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
7316b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7317b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool op_has_longofs(int32_t instruction) {
7318b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  switch (getop(instruction)) {
7319b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_CALL:
7320b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_BRANCH:
7321b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_CHECKDELIM:
7322b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return true;
7323b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* The "tag" instructions only have 8 bytes available for the jump target,
7324b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * but that is ok because these opcodes only require short jumps. */
7325b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_TAG1:
7326b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_TAG2:
7327b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_TAGN:
7328b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return false;
7329b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    default:
7330b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      assert(false);
7331b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return false;
7332b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
7333b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
7334b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7335b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic int32_t getofs(uint32_t instruction) {
7336b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (op_has_longofs(instruction)) {
7337b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return (int32_t)instruction >> 8;
7338b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
7339b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return (int8_t)(instruction >> 8);
7340b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
7341b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
7342b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7343b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void setofs(uint32_t *instruction, int32_t ofs) {
7344b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (op_has_longofs(*instruction)) {
7345b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    *instruction = getop(*instruction) | ofs << 8;
7346b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
7347b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    *instruction = (*instruction & ~0xff00) | ((ofs & 0xff) << 8);
7348b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
7349b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(getofs(*instruction) == ofs);  /* Would fail in cases of overflow. */
7350b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
7351b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7352b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic uint32_t pcofs(compiler *c) { return c->pc - c->group->bytecode; }
7353b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7354b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Defines a local label at the current PC location.  All previous forward
7355b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * references are updated to point to this location.  The location is noted
7356b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * for any future backward references. */
7357b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void label(compiler *c, unsigned int label) {
7358b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  int val;
7359b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  uint32_t *codep;
7360b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7361b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(label < MAXLABEL);
7362b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  val = c->fwd_labels[label];
7363b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  codep = (val == EMPTYLABEL) ? NULL : c->group->bytecode + val;
7364b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  while (codep) {
7365b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    int ofs = getofs(*codep);
7366b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    setofs(codep, c->pc - codep - instruction_len(*codep));
7367b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    codep = ofs ? codep + ofs : NULL;
7368b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
7369b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  c->fwd_labels[label] = EMPTYLABEL;
7370b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  c->back_labels[label] = pcofs(c);
7371b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
7372b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7373b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Creates a reference to a numbered label; either a forward reference
7374b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * (positive arg) or backward reference (negative arg).  For forward references
7375b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * the value returned now is actually a "next" pointer into a linked list of all
7376b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * instructions that use this label and will be patched later when the label is
7377b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * defined with label().
7378b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *
7379b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * The returned value is the offset that should be written into the instruction.
7380b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */
7381b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic int32_t labelref(compiler *c, int label) {
7382b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(label < MAXLABEL);
7383b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (label == LABEL_DISPATCH) {
7384b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* No resolving required. */
7385b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return 0;
7386b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else if (label < 0) {
7387b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Backward local label.  Relative to the next instruction. */
7388b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    uint32_t from = (c->pc + 1) - c->group->bytecode;
7389b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return c->back_labels[-label] - from;
7390b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
7391b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Forward local label: prepend to (possibly-empty) linked list. */
7392b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    int *lptr = &c->fwd_labels[label];
7393b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    int32_t ret = (*lptr == EMPTYLABEL) ? 0 : *lptr - pcofs(c);
7394b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    *lptr = pcofs(c);
7395b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return ret;
7396b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
7397b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
7398b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7399b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void put32(compiler *c, uint32_t v) {
7400b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  mgroup *g = c->group;
7401b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (c->pc == g->bytecode_end) {
7402b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    int ofs = pcofs(c);
7403b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    size_t oldsize = g->bytecode_end - g->bytecode;
7404b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    size_t newsize = UPB_MAX(oldsize * 2, 64);
7405b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* TODO(haberman): handle OOM. */
7406b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    g->bytecode = upb_grealloc(g->bytecode, oldsize * sizeof(uint32_t),
7407b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                            newsize * sizeof(uint32_t));
7408b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    g->bytecode_end = g->bytecode + newsize;
7409b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    c->pc = g->bytecode + ofs;
7410b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
7411b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  *c->pc++ = v;
7412b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
7413b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7414b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void putop(compiler *c, opcode op, ...) {
7415b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  va_list ap;
7416b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  va_start(ap, op);
7417b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7418b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  switch (op) {
7419b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_SETDISPATCH: {
7420b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      uintptr_t ptr = (uintptr_t)va_arg(ap, void*);
7421b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      put32(c, OP_SETDISPATCH);
7422b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      put32(c, ptr);
7423b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (sizeof(uintptr_t) > sizeof(uint32_t))
7424b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        put32(c, (uint64_t)ptr >> 32);
7425b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
7426b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
7427b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_STARTMSG:
7428b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_ENDMSG:
7429b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_PUSHLENDELIM:
7430b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_POP:
7431b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_SETDELIM:
7432b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_HALT:
7433b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_RET:
7434b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_DISPATCH:
7435b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      put32(c, op);
7436b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
7437b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_PARSE_DOUBLE:
7438b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_PARSE_FLOAT:
7439b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_PARSE_INT64:
7440b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_PARSE_UINT64:
7441b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_PARSE_INT32:
7442b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_PARSE_FIXED64:
7443b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_PARSE_FIXED32:
7444b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_PARSE_BOOL:
7445b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_PARSE_UINT32:
7446b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_PARSE_SFIXED32:
7447b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_PARSE_SFIXED64:
7448b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_PARSE_SINT32:
7449b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_PARSE_SINT64:
7450b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_STARTSEQ:
7451b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_ENDSEQ:
7452b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_STARTSUBMSG:
7453b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_ENDSUBMSG:
7454b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_STARTSTR:
7455b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_STRING:
7456b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_ENDSTR:
7457b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_PUSHTAGDELIM:
7458b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      put32(c, op | va_arg(ap, upb_selector_t) << 8);
7459b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
7460b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_SETBIGGROUPNUM:
7461b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      put32(c, op);
7462b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      put32(c, va_arg(ap, int));
7463b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
7464b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_CALL: {
7465b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      const upb_pbdecodermethod *method = va_arg(ap, upb_pbdecodermethod *);
7466b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      put32(c, op | (method->code_base.ofs - (pcofs(c) + 1)) << 8);
7467b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
7468b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
7469b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_CHECKDELIM:
7470b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_BRANCH: {
7471b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      uint32_t instruction = op;
7472b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      int label = va_arg(ap, int);
7473b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      setofs(&instruction, labelref(c, label));
7474b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      put32(c, instruction);
7475b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
7476b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
7477b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_TAG1:
7478b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_TAG2: {
7479b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      int label = va_arg(ap, int);
7480b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      uint64_t tag = va_arg(ap, uint64_t);
7481b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      uint32_t instruction = op | (tag << 16);
7482b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      assert(tag <= 0xffff);
7483b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      setofs(&instruction, labelref(c, label));
7484b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      put32(c, instruction);
7485b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
7486b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
7487b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_TAGN: {
7488b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      int label = va_arg(ap, int);
7489b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      uint64_t tag = va_arg(ap, uint64_t);
7490b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      uint32_t instruction = op | (upb_value_size(tag) << 16);
7491b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      setofs(&instruction, labelref(c, label));
7492b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      put32(c, instruction);
7493b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      put32(c, tag);
7494b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      put32(c, tag >> 32);
7495b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
7496b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
7497b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
7498b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7499b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  va_end(ap);
7500b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
7501b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7502b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#if defined(UPB_USE_JIT_X64) || defined(UPB_DUMP_BYTECODE)
7503b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7504b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst char *upb_pbdecoder_getopname(unsigned int op) {
7505b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#define QUOTE(x) #x
7506b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#define EXPAND_AND_QUOTE(x) QUOTE(x)
7507b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#define OPNAME(x) OP_##x
7508b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#define OP(x) case OPNAME(x): return EXPAND_AND_QUOTE(OPNAME(x));
7509b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#define T(x) OP(PARSE_##x)
7510b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Keep in sync with list in decoder.int.h. */
7511b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  switch ((opcode)op) {
7512b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    T(DOUBLE) T(FLOAT) T(INT64) T(UINT64) T(INT32) T(FIXED64) T(FIXED32)
7513b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    T(BOOL) T(UINT32) T(SFIXED32) T(SFIXED64) T(SINT32) T(SINT64)
7514b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    OP(STARTMSG) OP(ENDMSG) OP(STARTSEQ) OP(ENDSEQ) OP(STARTSUBMSG)
7515b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    OP(ENDSUBMSG) OP(STARTSTR) OP(STRING) OP(ENDSTR) OP(CALL) OP(RET)
7516b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    OP(PUSHLENDELIM) OP(PUSHTAGDELIM) OP(SETDELIM) OP(CHECKDELIM)
7517b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    OP(BRANCH) OP(TAG1) OP(TAG2) OP(TAGN) OP(SETDISPATCH) OP(POP)
7518b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    OP(SETBIGGROUPNUM) OP(DISPATCH) OP(HALT)
7519b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
7520b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return "<unknown op>";
7521b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#undef OP
7522b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#undef T
7523b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
7524b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7525b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#endif
7526b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7527b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#ifdef UPB_DUMP_BYTECODE
7528b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7529b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void dumpbc(uint32_t *p, uint32_t *end, FILE *f) {
7530b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7531b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  uint32_t *begin = p;
7532b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7533b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  while (p < end) {
7534b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    fprintf(f, "%p  %8tx", p, p - begin);
7535b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    uint32_t instr = *p++;
7536b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    uint8_t op = getop(instr);
7537b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    fprintf(f, " %s", upb_pbdecoder_getopname(op));
7538b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    switch ((opcode)op) {
7539b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case OP_SETDISPATCH: {
7540b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        const upb_inttable *dispatch;
7541b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        memcpy(&dispatch, p, sizeof(void*));
7542b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        p += ptr_words;
7543b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        const upb_pbdecodermethod *method =
7544b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer            (void *)((char *)dispatch -
7545b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                     offsetof(upb_pbdecodermethod, dispatch));
7546b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        fprintf(f, " %s", upb_msgdef_fullname(
7547b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                              upb_handlers_msgdef(method->dest_handlers_)));
7548b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        break;
7549b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
7550b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case OP_DISPATCH:
7551b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case OP_STARTMSG:
7552b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case OP_ENDMSG:
7553b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case OP_PUSHLENDELIM:
7554b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case OP_POP:
7555b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case OP_SETDELIM:
7556b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case OP_HALT:
7557b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case OP_RET:
7558b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        break;
7559b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case OP_PARSE_DOUBLE:
7560b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case OP_PARSE_FLOAT:
7561b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case OP_PARSE_INT64:
7562b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case OP_PARSE_UINT64:
7563b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case OP_PARSE_INT32:
7564b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case OP_PARSE_FIXED64:
7565b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case OP_PARSE_FIXED32:
7566b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case OP_PARSE_BOOL:
7567b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case OP_PARSE_UINT32:
7568b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case OP_PARSE_SFIXED32:
7569b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case OP_PARSE_SFIXED64:
7570b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case OP_PARSE_SINT32:
7571b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case OP_PARSE_SINT64:
7572b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case OP_STARTSEQ:
7573b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case OP_ENDSEQ:
7574b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case OP_STARTSUBMSG:
7575b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case OP_ENDSUBMSG:
7576b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case OP_STARTSTR:
7577b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case OP_STRING:
7578b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case OP_ENDSTR:
7579b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case OP_PUSHTAGDELIM:
7580b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        fprintf(f, " %d", instr >> 8);
7581b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        break;
7582b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case OP_SETBIGGROUPNUM:
7583b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        fprintf(f, " %d", *p++);
7584b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        break;
7585b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case OP_CHECKDELIM:
7586b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case OP_CALL:
7587b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case OP_BRANCH:
7588b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        fprintf(f, " =>0x%tx", p + getofs(instr) - begin);
7589b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        break;
7590b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case OP_TAG1:
7591b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case OP_TAG2: {
7592b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        fprintf(f, " tag:0x%x", instr >> 16);
7593b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        if (getofs(instr)) {
7594b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          fprintf(f, " =>0x%tx", p + getofs(instr) - begin);
7595b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        }
7596b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        break;
7597b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
7598b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case OP_TAGN: {
7599b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        uint64_t tag = *p++;
7600b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        tag |= (uint64_t)*p++ << 32;
7601b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        fprintf(f, " tag:0x%llx", (long long)tag);
7602b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        fprintf(f, " n:%d", instr >> 16);
7603b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        if (getofs(instr)) {
7604b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          fprintf(f, " =>0x%tx", p + getofs(instr) - begin);
7605b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        }
7606b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        break;
7607b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
7608b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
7609b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    fputs("\n", f);
7610b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
7611b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
7612b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7613b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#endif
7614b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7615b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic uint64_t get_encoded_tag(const upb_fielddef *f, int wire_type) {
7616b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  uint32_t tag = (upb_fielddef_number(f) << 3) | wire_type;
7617b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  uint64_t encoded_tag = upb_vencode32(tag);
7618b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* No tag should be greater than 5 bytes. */
7619b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(encoded_tag <= 0xffffffffff);
7620b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return encoded_tag;
7621b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
7622b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7623b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void putchecktag(compiler *c, const upb_fielddef *f,
7624b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                        int wire_type, int dest) {
7625b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  uint64_t tag = get_encoded_tag(f, wire_type);
7626b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  switch (upb_value_size(tag)) {
7627b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case 1:
7628b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      putop(c, OP_TAG1, dest, tag);
7629b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
7630b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case 2:
7631b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      putop(c, OP_TAG2, dest, tag);
7632b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
7633b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    default:
7634b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      putop(c, OP_TAGN, dest, tag);
7635b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
7636b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
7637b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
7638b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7639b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic upb_selector_t getsel(const upb_fielddef *f, upb_handlertype_t type) {
7640b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_selector_t selector;
7641b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bool ok = upb_handlers_getselector(f, type, &selector);
7642b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_ASSERT_VAR(ok, ok);
7643b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return selector;
7644b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
7645b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7646b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Takes an existing, primary dispatch table entry and repacks it with a
7647b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * different alternate wire type.  Called when we are inserting a secondary
7648b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * dispatch table entry for an alternate wire type. */
7649b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic uint64_t repack(uint64_t dispatch, int new_wt2) {
7650b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  uint64_t ofs;
7651b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  uint8_t wt1;
7652b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  uint8_t old_wt2;
7653b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_pbdecoder_unpackdispatch(dispatch, &ofs, &wt1, &old_wt2);
7654b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(old_wt2 == NO_WIRE_TYPE);  /* wt2 should not be set yet. */
7655b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_pbdecoder_packdispatch(ofs, wt1, new_wt2);
7656b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
7657b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7658b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Marks the current bytecode position as the dispatch target for this message,
7659b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * field, and wire type. */
7660b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void dispatchtarget(compiler *c, upb_pbdecodermethod *method,
7661b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                           const upb_fielddef *f, int wire_type) {
7662b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Offset is relative to msg base. */
7663b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  uint64_t ofs = pcofs(c) - method->code_base.ofs;
7664b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  uint32_t fn = upb_fielddef_number(f);
7665b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable *d = &method->dispatch;
7666b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_value v;
7667b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upb_inttable_remove(d, fn, &v)) {
7668b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* TODO: prioritize based on packed setting in .proto file. */
7669b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    uint64_t repacked = repack(upb_value_getuint64(v), wire_type);
7670b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_inttable_insert(d, fn, upb_value_uint64(repacked));
7671b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_inttable_insert(d, fn + UPB_MAX_FIELDNUMBER, upb_value_uint64(ofs));
7672b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
7673b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    uint64_t val = upb_pbdecoder_packdispatch(ofs, wire_type, NO_WIRE_TYPE);
7674b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_inttable_insert(d, fn, upb_value_uint64(val));
7675b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
7676b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
7677b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7678b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void putpush(compiler *c, const upb_fielddef *f) {
7679b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upb_fielddef_descriptortype(f) == UPB_DESCRIPTOR_TYPE_MESSAGE) {
7680b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putop(c, OP_PUSHLENDELIM);
7681b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
7682b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    uint32_t fn = upb_fielddef_number(f);
7683b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (fn >= 1 << 24) {
7684b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      putop(c, OP_PUSHTAGDELIM, 0);
7685b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      putop(c, OP_SETBIGGROUPNUM, fn);
7686b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    } else {
7687b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      putop(c, OP_PUSHTAGDELIM, fn);
7688b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
7689b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
7690b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
7691b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7692b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic upb_pbdecodermethod *find_submethod(const compiler *c,
7693b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                           const upb_pbdecodermethod *method,
7694b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                           const upb_fielddef *f) {
7695b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const upb_handlers *sub =
7696b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_handlers_getsubhandlers(method->dest_handlers_, f);
7697b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_value v;
7698b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_inttable_lookupptr(&c->group->methods, sub, &v)
7699b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer             ? upb_value_getptr(v)
7700b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer             : NULL;
7701b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
7702b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7703b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void putsel(compiler *c, opcode op, upb_selector_t sel,
7704b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                   const upb_handlers *h) {
7705b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upb_handlers_gethandler(h, sel)) {
7706b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putop(c, op, sel);
7707b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
7708b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
7709b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7710b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Puts an opcode to call a callback, but only if a callback actually exists for
7711b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * this field and handler type. */
7712b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void maybeput(compiler *c, opcode op, const upb_handlers *h,
7713b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                     const upb_fielddef *f, upb_handlertype_t type) {
7714b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  putsel(c, op, getsel(f, type), h);
7715b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
7716b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7717b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool haslazyhandlers(const upb_handlers *h, const upb_fielddef *f) {
7718b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!upb_fielddef_lazy(f))
7719b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
7720b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7721b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_handlers_gethandler(h, getsel(f, UPB_HANDLER_STARTSTR)) ||
7722b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer         upb_handlers_gethandler(h, getsel(f, UPB_HANDLER_STRING)) ||
7723b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer         upb_handlers_gethandler(h, getsel(f, UPB_HANDLER_ENDSTR));
7724b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
7725b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7726b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7727b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* bytecode compiler code generation ******************************************/
7728b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7729b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Symbolic names for our local labels. */
7730b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#define LABEL_LOOPSTART 1  /* Top of a repeated field loop. */
7731b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#define LABEL_LOOPBREAK 2  /* To jump out of a repeated loop */
7732b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#define LABEL_FIELD     3  /* Jump backward to find the most recent field. */
7733b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#define LABEL_ENDMSG    4  /* To reach the OP_ENDMSG instr for this msg. */
7734b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7735b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Generates bytecode to parse a single non-lazy message field. */
7736b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void generate_msgfield(compiler *c, const upb_fielddef *f,
7737b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                              upb_pbdecodermethod *method) {
7738b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const upb_handlers *h = upb_pbdecodermethod_desthandlers(method);
7739b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const upb_pbdecodermethod *sub_m = find_submethod(c, method, f);
7740b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  int wire_type;
7741b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7742b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!sub_m) {
7743b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Don't emit any code for this field at all; it will be parsed as an
7744b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * unknown field.
7745b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     *
7746b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * TODO(haberman): we should change this to parse it as a string field
7747b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * instead.  It will probably be faster, but more importantly, once we
7748b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * start vending unknown fields, a field shouldn't be treated as unknown
7749b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * just because it doesn't have subhandlers registered. */
7750b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return;
7751b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
7752b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7753b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  label(c, LABEL_FIELD);
7754b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7755b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  wire_type =
7756b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      (upb_fielddef_descriptortype(f) == UPB_DESCRIPTOR_TYPE_MESSAGE)
7757b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          ? UPB_WIRE_TYPE_DELIMITED
7758b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          : UPB_WIRE_TYPE_START_GROUP;
7759b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7760b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upb_fielddef_isseq(f)) {
7761b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
7762b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putchecktag(c, f, wire_type, LABEL_DISPATCH);
7763b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   dispatchtarget(c, method, f, wire_type);
7764b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putop(c, OP_PUSHTAGDELIM, 0);
7765b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putop(c, OP_STARTSEQ, getsel(f, UPB_HANDLER_STARTSEQ));
7766b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   label(c, LABEL_LOOPSTART);
7767b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putpush(c, f);
7768b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putop(c, OP_STARTSUBMSG, getsel(f, UPB_HANDLER_STARTSUBMSG));
7769b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putop(c, OP_CALL, sub_m);
7770b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putop(c, OP_POP);
7771b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    maybeput(c, OP_ENDSUBMSG, h, f, UPB_HANDLER_ENDSUBMSG);
7772b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (wire_type == UPB_WIRE_TYPE_DELIMITED) {
7773b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      putop(c, OP_SETDELIM);
7774b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
7775b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putop(c, OP_CHECKDELIM, LABEL_LOOPBREAK);
7776b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putchecktag(c, f, wire_type, LABEL_LOOPBREAK);
7777b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putop(c, OP_BRANCH, -LABEL_LOOPSTART);
7778b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   label(c, LABEL_LOOPBREAK);
7779b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putop(c, OP_POP);
7780b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    maybeput(c, OP_ENDSEQ, h, f, UPB_HANDLER_ENDSEQ);
7781b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
7782b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
7783b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putchecktag(c, f, wire_type, LABEL_DISPATCH);
7784b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   dispatchtarget(c, method, f, wire_type);
7785b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putpush(c, f);
7786b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putop(c, OP_STARTSUBMSG, getsel(f, UPB_HANDLER_STARTSUBMSG));
7787b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putop(c, OP_CALL, sub_m);
7788b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putop(c, OP_POP);
7789b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    maybeput(c, OP_ENDSUBMSG, h, f, UPB_HANDLER_ENDSUBMSG);
7790b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (wire_type == UPB_WIRE_TYPE_DELIMITED) {
7791b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      putop(c, OP_SETDELIM);
7792b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
7793b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
7794b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
7795b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7796b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Generates bytecode to parse a single string or lazy submessage field. */
7797b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void generate_delimfield(compiler *c, const upb_fielddef *f,
7798b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                upb_pbdecodermethod *method) {
7799b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const upb_handlers *h = upb_pbdecodermethod_desthandlers(method);
7800b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7801b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  label(c, LABEL_FIELD);
7802b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upb_fielddef_isseq(f)) {
7803b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
7804b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putchecktag(c, f, UPB_WIRE_TYPE_DELIMITED, LABEL_DISPATCH);
7805b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   dispatchtarget(c, method, f, UPB_WIRE_TYPE_DELIMITED);
7806b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putop(c, OP_PUSHTAGDELIM, 0);
7807b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putop(c, OP_STARTSEQ, getsel(f, UPB_HANDLER_STARTSEQ));
7808b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   label(c, LABEL_LOOPSTART);
7809b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putop(c, OP_PUSHLENDELIM);
7810b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putop(c, OP_STARTSTR, getsel(f, UPB_HANDLER_STARTSTR));
7811b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Need to emit even if no handler to skip past the string. */
7812b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putop(c, OP_STRING, getsel(f, UPB_HANDLER_STRING));
7813b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putop(c, OP_POP);
7814b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    maybeput(c, OP_ENDSTR, h, f, UPB_HANDLER_ENDSTR);
7815b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putop(c, OP_SETDELIM);
7816b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putop(c, OP_CHECKDELIM, LABEL_LOOPBREAK);
7817b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putchecktag(c, f, UPB_WIRE_TYPE_DELIMITED, LABEL_LOOPBREAK);
7818b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putop(c, OP_BRANCH, -LABEL_LOOPSTART);
7819b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   label(c, LABEL_LOOPBREAK);
7820b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putop(c, OP_POP);
7821b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    maybeput(c, OP_ENDSEQ, h, f, UPB_HANDLER_ENDSEQ);
7822b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
7823b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
7824b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putchecktag(c, f, UPB_WIRE_TYPE_DELIMITED, LABEL_DISPATCH);
7825b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   dispatchtarget(c, method, f, UPB_WIRE_TYPE_DELIMITED);
7826b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putop(c, OP_PUSHLENDELIM);
7827b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putop(c, OP_STARTSTR, getsel(f, UPB_HANDLER_STARTSTR));
7828b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putop(c, OP_STRING, getsel(f, UPB_HANDLER_STRING));
7829b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putop(c, OP_POP);
7830b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    maybeput(c, OP_ENDSTR, h, f, UPB_HANDLER_ENDSTR);
7831b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putop(c, OP_SETDELIM);
7832b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
7833b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
7834b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7835b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Generates bytecode to parse a single primitive field. */
7836b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void generate_primitivefield(compiler *c, const upb_fielddef *f,
7837b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                    upb_pbdecodermethod *method) {
7838b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const upb_handlers *h = upb_pbdecodermethod_desthandlers(method);
7839b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_descriptortype_t descriptor_type = upb_fielddef_descriptortype(f);
7840b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  opcode parse_type;
7841b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_selector_t sel;
7842b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  int wire_type;
7843b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7844b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  label(c, LABEL_FIELD);
7845b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7846b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* From a decoding perspective, ENUM is the same as INT32. */
7847b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (descriptor_type == UPB_DESCRIPTOR_TYPE_ENUM)
7848b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    descriptor_type = UPB_DESCRIPTOR_TYPE_INT32;
7849b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7850b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  parse_type = (opcode)descriptor_type;
7851b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7852b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* TODO(haberman): generate packed or non-packed first depending on "packed"
7853b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * setting in the fielddef.  This will favor (in speed) whichever was
7854b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * specified. */
7855b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7856b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert((int)parse_type >= 0 && parse_type <= OP_MAX);
7857b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  sel = getsel(f, upb_handlers_getprimitivehandlertype(f));
7858b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  wire_type = upb_pb_native_wire_types[upb_fielddef_descriptortype(f)];
7859b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upb_fielddef_isseq(f)) {
7860b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
7861b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putchecktag(c, f, UPB_WIRE_TYPE_DELIMITED, LABEL_DISPATCH);
7862b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   dispatchtarget(c, method, f, UPB_WIRE_TYPE_DELIMITED);
7863b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putop(c, OP_PUSHLENDELIM);
7864b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putop(c, OP_STARTSEQ, getsel(f, UPB_HANDLER_STARTSEQ));  /* Packed */
7865b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   label(c, LABEL_LOOPSTART);
7866b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putop(c, parse_type, sel);
7867b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putop(c, OP_CHECKDELIM, LABEL_LOOPBREAK);
7868b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putop(c, OP_BRANCH, -LABEL_LOOPSTART);
7869b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   dispatchtarget(c, method, f, wire_type);
7870b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putop(c, OP_PUSHTAGDELIM, 0);
7871b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putop(c, OP_STARTSEQ, getsel(f, UPB_HANDLER_STARTSEQ));  /* Non-packed */
7872b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   label(c, LABEL_LOOPSTART);
7873b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putop(c, parse_type, sel);
7874b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putop(c, OP_CHECKDELIM, LABEL_LOOPBREAK);
7875b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putchecktag(c, f, wire_type, LABEL_LOOPBREAK);
7876b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putop(c, OP_BRANCH, -LABEL_LOOPSTART);
7877b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   label(c, LABEL_LOOPBREAK);
7878b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putop(c, OP_POP);  /* Packed and non-packed join. */
7879b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    maybeput(c, OP_ENDSEQ, h, f, UPB_HANDLER_ENDSEQ);
7880b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putop(c, OP_SETDELIM);  /* Could remove for non-packed by dup ENDSEQ. */
7881b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
7882b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
7883b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putchecktag(c, f, wire_type, LABEL_DISPATCH);
7884b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   dispatchtarget(c, method, f, wire_type);
7885b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putop(c, parse_type, sel);
7886b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
7887b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
7888b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7889b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Adds bytecode for parsing the given message to the given decoderplan,
7890b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * while adding all dispatch targets to this message's dispatch table. */
7891b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void compile_method(compiler *c, upb_pbdecodermethod *method) {
7892b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const upb_handlers *h;
7893b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const upb_msgdef *md;
7894b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  uint32_t* start_pc;
7895b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_msg_field_iter i;
7896b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_value val;
7897b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7898b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(method);
7899b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7900b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Clear all entries in the dispatch table. */
7901b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_uninit(&method->dispatch);
7902b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_init(&method->dispatch, UPB_CTYPE_UINT64);
7903b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7904b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  h = upb_pbdecodermethod_desthandlers(method);
7905b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  md = upb_handlers_msgdef(h);
7906b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7907b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer method->code_base.ofs = pcofs(c);
7908b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  putop(c, OP_SETDISPATCH, &method->dispatch);
7909b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  putsel(c, OP_STARTMSG, UPB_STARTMSG_SELECTOR, h);
7910b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer label(c, LABEL_FIELD);
7911b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  start_pc = c->pc;
7912b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for(upb_msg_field_begin(&i, md);
7913b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      !upb_msg_field_done(&i);
7914b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_msg_field_next(&i)) {
7915b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    const upb_fielddef *f = upb_msg_iter_field(&i);
7916b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_fieldtype_t type = upb_fielddef_type(f);
7917b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7918b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (type == UPB_TYPE_MESSAGE && !(haslazyhandlers(h, f) && c->lazy)) {
7919b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      generate_msgfield(c, f, method);
7920b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    } else if (type == UPB_TYPE_STRING || type == UPB_TYPE_BYTES ||
7921b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer               type == UPB_TYPE_MESSAGE) {
7922b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      generate_delimfield(c, f, method);
7923b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    } else {
7924b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      generate_primitivefield(c, f, method);
7925b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
7926b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
7927b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7928b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* If there were no fields, or if no handlers were defined, we need to
7929b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * generate a non-empty loop body so that we can at least dispatch for unknown
7930b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * fields and check for the end of the message. */
7931b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (c->pc == start_pc) {
7932b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Check for end-of-message. */
7933b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
7934b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Unconditionally dispatch. */
7935b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putop(c, OP_DISPATCH, 0);
7936b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
7937b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7938b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* For now we just loop back to the last field of the message (or if none,
7939b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * the DISPATCH opcode for the message). */
7940b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  putop(c, OP_BRANCH, -LABEL_FIELD);
7941b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7942b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Insert both a label and a dispatch table entry for this end-of-msg. */
7943b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer label(c, LABEL_ENDMSG);
7944b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  val = upb_value_uint64(pcofs(c) - method->code_base.ofs);
7945b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_insert(&method->dispatch, DISPATCH_ENDMSG, val);
7946b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7947b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  putsel(c, OP_ENDMSG, UPB_ENDMSG_SELECTOR, h);
7948b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  putop(c, OP_RET);
7949b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7950b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_compact(&method->dispatch);
7951b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
7952b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7953b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Populate "methods" with new upb_pbdecodermethod objects reachable from "h".
7954b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Returns the method for these handlers.
7955b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *
7956b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Generates a new method for every destination handlers reachable from "h". */
7957b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void find_methods(compiler *c, const upb_handlers *h) {
7958b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_value v;
7959b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_msg_field_iter i;
7960b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const upb_msgdef *md;
7961b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7962b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upb_inttable_lookupptr(&c->group->methods, h, &v))
7963b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return;
7964b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  newmethod(h, c->group);
7965b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7966b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Find submethods. */
7967b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  md = upb_handlers_msgdef(h);
7968b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for(upb_msg_field_begin(&i, md);
7969b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      !upb_msg_field_done(&i);
7970b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_msg_field_next(&i)) {
7971b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    const upb_fielddef *f = upb_msg_iter_field(&i);
7972b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    const upb_handlers *sub_h;
7973b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (upb_fielddef_type(f) == UPB_TYPE_MESSAGE &&
7974b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        (sub_h = upb_handlers_getsubhandlers(h, f)) != NULL) {
7975b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      /* We only generate a decoder method for submessages with handlers.
7976b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer       * Others will be parsed as unknown fields. */
7977b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      find_methods(c, sub_h);
7978b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
7979b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
7980b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
7981b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7982b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* (Re-)compile bytecode for all messages in "msgs."
7983b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Overwrites any existing bytecode in "c". */
7984b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void compile_methods(compiler *c) {
7985b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_iter i;
7986b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7987b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Start over at the beginning of the bytecode. */
7988b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  c->pc = c->group->bytecode;
7989b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7990b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_begin(&i, &c->group->methods);
7991b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
7992b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_pbdecodermethod *method = upb_value_getptr(upb_inttable_iter_value(&i));
7993b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    compile_method(c, method);
7994b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
7995b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
7996b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
7997b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void set_bytecode_handlers(mgroup *g) {
7998b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_iter i;
7999b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_begin(&i, &g->methods);
8000b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
8001b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_pbdecodermethod *m = upb_value_getptr(upb_inttable_iter_value(&i));
8002b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_byteshandler *h = &m->input_handler_;
8003b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8004b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    m->code_base.ptr = g->bytecode + m->code_base.ofs;
8005b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8006b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_byteshandler_setstartstr(h, upb_pbdecoder_startbc, m->code_base.ptr);
8007b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_byteshandler_setstring(h, upb_pbdecoder_decode, g);
8008b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_byteshandler_setendstr(h, upb_pbdecoder_end, m);
8009b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
8010b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
8011b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8012b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8013b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* JIT setup. *****************************************************************/
8014b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8015b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#ifdef UPB_USE_JIT_X64
8016b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8017b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void sethandlers(mgroup *g, bool allowjit) {
8018b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  g->jit_code = NULL;
8019b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (allowjit) {
8020b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Compile byte-code into machine code, create handlers. */
8021b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_pbdecoder_jit(g);
8022b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
8023b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    set_bytecode_handlers(g);
8024b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
8025b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
8026b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8027b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#else  /* UPB_USE_JIT_X64 */
8028b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8029b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void sethandlers(mgroup *g, bool allowjit) {
8030b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* No JIT compiled in; use bytecode handlers unconditionally. */
8031b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(allowjit);
8032b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  set_bytecode_handlers(g);
8033b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
8034b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8035b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#endif  /* UPB_USE_JIT_X64 */
8036b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8037b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8038b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* TODO(haberman): allow this to be constructed for an arbitrary set of dest
8039b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * handlers and other mgroups (but verify we have a transitive closure). */
8040b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst mgroup *mgroup_new(const upb_handlers *dest, bool allowjit, bool lazy,
8041b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                         const void *owner) {
8042b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  mgroup *g;
8043b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  compiler *c;
8044b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8045b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(allowjit);
8046b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(upb_handlers_isfrozen(dest));
8047b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8048b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  g = newgroup(owner);
8049b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  c = newcompiler(g, lazy);
8050b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  find_methods(c, dest);
8051b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8052b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* We compile in two passes:
8053b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * 1. all messages are assigned relative offsets from the beginning of the
8054b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   *    bytecode (saved in method->code_base).
8055b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * 2. forwards OP_CALL instructions can be correctly linked since message
8056b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   *    offsets have been previously assigned.
8057b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   *
8058b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * Could avoid the second pass by linking OP_CALL instructions somehow. */
8059b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  compile_methods(c);
8060b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  compile_methods(c);
8061b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  g->bytecode_end = c->pc;
8062b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  freecompiler(c);
8063b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8064b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#ifdef UPB_DUMP_BYTECODE
8065b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {
8066b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    FILE *f = fopen("/tmp/upb-bytecode", "w");
8067b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    assert(f);
8068b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    dumpbc(g->bytecode, g->bytecode_end, stderr);
8069b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    dumpbc(g->bytecode, g->bytecode_end, f);
8070b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    fclose(f);
8071b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8072b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    f = fopen("/tmp/upb-bytecode.bin", "wb");
8073b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    assert(f);
8074b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    fwrite(g->bytecode, 1, g->bytecode_end - g->bytecode, f);
8075b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    fclose(f);
8076b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
8077b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#endif
8078b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8079b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  sethandlers(g, allowjit);
8080b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return g;
8081b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
8082b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8083b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8084b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* upb_pbcodecache ************************************************************/
8085b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8086b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_pbcodecache_init(upb_pbcodecache *c) {
8087b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_init(&c->groups, UPB_CTYPE_CONSTPTR);
8088b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  c->allow_jit_ = true;
8089b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
8090b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8091b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_pbcodecache_uninit(upb_pbcodecache *c) {
8092b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_iter i;
8093b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_begin(&i, &c->groups);
8094b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
8095b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    const mgroup *group = upb_value_getconstptr(upb_inttable_iter_value(&i));
8096b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    mgroup_unref(group, c);
8097b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
8098b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_uninit(&c->groups);
8099b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
8100b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8101b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_pbcodecache_allowjit(const upb_pbcodecache *c) {
8102b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return c->allow_jit_;
8103b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
8104b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8105b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_pbcodecache_setallowjit(upb_pbcodecache *c, bool allow) {
8106b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upb_inttable_count(&c->groups) > 0)
8107b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
8108b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  c->allow_jit_ = allow;
8109b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
8110b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
8111b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8112b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_pbdecodermethod *upb_pbcodecache_getdecodermethod(
8113b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_pbcodecache *c, const upb_pbdecodermethodopts *opts) {
8114b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_value v;
8115b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bool ok;
8116b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8117b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Right now we build a new DecoderMethod every time.
8118b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * TODO(haberman): properly cache methods by their true key. */
8119b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const mgroup *g = mgroup_new(opts->handlers, c->allow_jit_, opts->lazy, c);
8120b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_push(&c->groups, upb_value_constptr(g));
8121b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8122b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  ok = upb_inttable_lookupptr(&g->methods, opts->handlers, &v);
8123b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_ASSERT_VAR(ok, ok);
8124b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_value_getptr(v);
8125b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
8126b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8127b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8128b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* upb_pbdecodermethodopts ****************************************************/
8129b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8130b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_pbdecodermethodopts_init(upb_pbdecodermethodopts *opts,
8131b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                  const upb_handlers *h) {
8132b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  opts->handlers = h;
8133b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  opts->lazy = false;
8134b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
8135b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8136b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_pbdecodermethodopts_setlazy(upb_pbdecodermethodopts *opts, bool lazy) {
8137b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  opts->lazy = lazy;
8138b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
8139b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/*
8140b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** upb::Decoder (Bytecode Decoder VM)
8141b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer**
8142b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** Bytecode must previously have been generated using the bytecode compiler in
8143b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** compile_decoder.c.  This decoder then walks through the bytecode op-by-op to
8144b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** parse the input.
8145b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer**
8146b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** Decoding is fully resumable; we just keep a pointer to the current bytecode
8147b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** instruction and resume from there.  A fair amount of the logic here is to
8148b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** handle the fact that values can span buffer seams and we have to be able to
8149b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** be capable of suspending/resuming from any byte in the stream.  This
8150b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** sometimes requires keeping a few trailing bytes from the last buffer around
8151b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** in the "residual" buffer.
8152b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer*/
8153b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8154b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <inttypes.h>
8155b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <stddef.h>
8156b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8157b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#ifdef UPB_DUMP_BYTECODE
8158b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <stdio.h>
8159b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#endif
8160b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8161b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#define CHECK_SUSPEND(x) if (!(x)) return upb_pbdecoder_suspend(d);
8162b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8163b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Error messages that are shared between the bytecode and JIT decoders. */
8164b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst char *kPbDecoderStackOverflow = "Nesting too deep.";
8165b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst char *kPbDecoderSubmessageTooLong =
8166b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    "Submessage end extends past enclosing submessage.";
8167b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8168b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Error messages shared within this file. */
8169b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic const char *kUnterminatedVarint = "Unterminated varint.";
8170b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8171b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* upb_pbdecoder **************************************************************/
8172b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8173b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic opcode halt = OP_HALT;
8174b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8175b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* A dummy character we can point to when the user passes us a NULL buffer.
8176b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * We need this because in C (NULL + 0) and (NULL - NULL) are undefined
8177b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * behavior, which would invalidate functions like curbufleft(). */
8178b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic const char dummy_char;
8179b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8180b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Whether an op consumes any of the input buffer. */
8181b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool consumes_input(opcode op) {
8182b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  switch (op) {
8183b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_SETDISPATCH:
8184b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_STARTMSG:
8185b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_ENDMSG:
8186b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_STARTSEQ:
8187b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_ENDSEQ:
8188b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_STARTSUBMSG:
8189b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_ENDSUBMSG:
8190b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_STARTSTR:
8191b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_ENDSTR:
8192b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_PUSHTAGDELIM:
8193b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_POP:
8194b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_SETDELIM:
8195b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_SETBIGGROUPNUM:
8196b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_CHECKDELIM:
8197b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_CALL:
8198b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_RET:
8199b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case OP_BRANCH:
8200b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return false;
8201b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    default:
8202b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return true;
8203b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
8204b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
8205b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8206b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic size_t stacksize(upb_pbdecoder *d, size_t entries) {
8207b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(d);
8208b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return entries * sizeof(upb_pbdecoder_frame);
8209b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
8210b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8211b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic size_t callstacksize(upb_pbdecoder *d, size_t entries) {
8212b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(d);
8213b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8214b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#ifdef UPB_USE_JIT_X64
8215b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (d->method_->is_native_) {
8216b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Each native stack frame needs two pointers, plus we need a few frames for
8217b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * the enter/exit trampolines. */
8218b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    size_t ret = entries * sizeof(void*) * 2;
8219b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    ret += sizeof(void*) * 10;
8220b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return ret;
8221b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
8222b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#endif
8223b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8224b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return entries * sizeof(uint32_t*);
8225b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
8226b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8227b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8228b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool in_residual_buf(const upb_pbdecoder *d, const char *p);
8229b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8230b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* It's unfortunate that we have to micro-manage the compiler with
8231b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * UPB_FORCEINLINE and UPB_NOINLINE, especially since this tuning is necessarily
8232b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * specific to one hardware configuration.  But empirically on a Core i7,
8233b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * performance increases 30-50% with these annotations.  Every instance where
8234b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * these appear, gcc 4.2.1 made the wrong decision and degraded performance in
8235b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * benchmarks. */
8236b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8237b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void seterr(upb_pbdecoder *d, const char *msg) {
8238b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_status status = UPB_STATUS_INIT;
8239b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_status_seterrmsg(&status, msg);
8240b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_env_reporterror(d->env, &status);
8241b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
8242b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8243b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_pbdecoder_seterr(upb_pbdecoder *d, const char *msg) {
8244b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  seterr(d, msg);
8245b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
8246b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8247b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8248b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Buffering ******************************************************************/
8249b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8250b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* We operate on one buffer at a time, which is either the user's buffer passed
8251b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * to our "decode" callback or some residual bytes from the previous buffer. */
8252b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8253b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* How many bytes can be safely read from d->ptr without reading past end-of-buf
8254b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * or past the current delimited end. */
8255b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic size_t curbufleft(const upb_pbdecoder *d) {
8256b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(d->data_end >= d->ptr);
8257b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return d->data_end - d->ptr;
8258b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
8259b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8260b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* How many bytes are available before end-of-buffer. */
8261b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic size_t bufleft(const upb_pbdecoder *d) {
8262b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return d->end - d->ptr;
8263b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
8264b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8265b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Overall stream offset of d->ptr. */
8266b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammeruint64_t offset(const upb_pbdecoder *d) {
8267b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return d->bufstart_ofs + (d->ptr - d->buf);
8268b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
8269b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8270b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* How many bytes are available before the end of this delimited region. */
8271b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammersize_t delim_remaining(const upb_pbdecoder *d) {
8272b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return d->top->end_ofs - offset(d);
8273b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
8274b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8275b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Advances d->ptr. */
8276b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void advance(upb_pbdecoder *d, size_t len) {
8277b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(curbufleft(d) >= len);
8278b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  d->ptr += len;
8279b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
8280b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8281b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool in_buf(const char *p, const char *buf, const char *end) {
8282b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return p >= buf && p <= end;
8283b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
8284b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8285b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool in_residual_buf(const upb_pbdecoder *d, const char *p) {
8286b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return in_buf(p, d->residual, d->residual_end);
8287b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
8288b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8289b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Calculates the delim_end value, which is affected by both the current buffer
8290b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * and the parsing stack, so must be called whenever either is updated. */
8291b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void set_delim_end(upb_pbdecoder *d) {
8292b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  size_t delim_ofs = d->top->end_ofs - d->bufstart_ofs;
8293b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (delim_ofs <= (size_t)(d->end - d->buf)) {
8294b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    d->delim_end = d->buf + delim_ofs;
8295b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    d->data_end = d->delim_end;
8296b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
8297b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    d->data_end = d->end;
8298b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    d->delim_end = NULL;
8299b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
8300b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
8301b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8302b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void switchtobuf(upb_pbdecoder *d, const char *buf, const char *end) {
8303b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  d->ptr = buf;
8304b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  d->buf = buf;
8305b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  d->end = end;
8306b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  set_delim_end(d);
8307b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
8308b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8309b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void advancetobuf(upb_pbdecoder *d, const char *buf, size_t len) {
8310b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(curbufleft(d) == 0);
8311b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  d->bufstart_ofs += (d->end - d->buf);
8312b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  switchtobuf(d, buf, buf + len);
8313b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
8314b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8315b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void checkpoint(upb_pbdecoder *d) {
8316b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* The assertion here is in the interests of efficiency, not correctness.
8317b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * We are trying to ensure that we don't checkpoint() more often than
8318b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * necessary. */
8319b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(d->checkpoint != d->ptr);
8320b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  d->checkpoint = d->ptr;
8321b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
8322b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8323b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Skips "bytes" bytes in the stream, which may be more than available.  If we
8324b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * skip more bytes than are available, we return a long read count to the caller
8325b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * indicating how many bytes can be skipped over before passing actual data
8326b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * again.  Skipped bytes can pass a NULL buffer and the decoder guarantees they
8327b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * won't actually be read.
8328b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */
8329b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic int32_t skip(upb_pbdecoder *d, size_t bytes) {
8330b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(!in_residual_buf(d, d->ptr) || d->size_param == 0);
8331b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(d->skip == 0);
8332b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (bytes > delim_remaining(d)) {
8333b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    seterr(d, "Skipped value extended beyond enclosing submessage.");
8334b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return upb_pbdecoder_suspend(d);
8335b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else if (bufleft(d) >= bytes) {
8336b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Skipped data is all in current buffer, and more is still available. */
8337b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    advance(d, bytes);
8338b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    d->skip = 0;
8339b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return DECODE_OK;
8340b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
8341b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Skipped data extends beyond currently available buffers. */
8342b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    d->pc = d->last;
8343b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    d->skip = bytes - curbufleft(d);
8344b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    d->bufstart_ofs += (d->end - d->buf);
8345b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    d->residual_end = d->residual;
8346b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    switchtobuf(d, d->residual, d->residual_end);
8347b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return d->size_param + d->skip;
8348b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
8349b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
8350b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8351b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8352b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Resumes the decoder from an initial state or from a previous suspend. */
8353b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerint32_t upb_pbdecoder_resume(upb_pbdecoder *d, void *p, const char *buf,
8354b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                             size_t size, const upb_bufhandle *handle) {
8355b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(p);  /* Useless; just for the benefit of the JIT. */
8356b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8357b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* d->skip and d->residual_end could probably elegantly be represented
8358b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * as a single variable, to more easily represent this invariant. */
8359b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(!(d->skip && d->residual_end > d->residual));
8360b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8361b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* We need to remember the original size_param, so that the value we return
8362b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * is relative to it, even if we do some skipping first. */
8363b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  d->size_param = size;
8364b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  d->handle = handle;
8365b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8366b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Have to handle this case specially (ie. not with skip()) because the user
8367b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * is allowed to pass a NULL buffer here, which won't allow us to safely
8368b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * calculate a d->end or use our normal functions like curbufleft(). */
8369b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (d->skip && d->skip >= size) {
8370b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    d->skip -= size;
8371b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    d->bufstart_ofs += size;
8372b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    buf = &dummy_char;
8373b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    size = 0;
8374b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8375b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* We can't just return now, because we might need to execute some ops
8376b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * like CHECKDELIM, which could call some callbacks and pop the stack. */
8377b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
8378b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8379b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* We need to pretend that this was the actual buffer param, since some of the
8380b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * calculations assume that d->ptr/d->buf is relative to this. */
8381b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  d->buf_param = buf;
8382b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8383b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!buf) {
8384b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* NULL buf is ok if its entire span is covered by the "skip" above, but
8385b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * by this point we know that "skip" doesn't cover the buffer. */
8386b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    seterr(d, "Passed NULL buffer over non-skippable region.");
8387b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return upb_pbdecoder_suspend(d);
8388b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
8389b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8390b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (d->residual_end > d->residual) {
8391b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* We have residual bytes from the last buffer. */
8392b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    assert(d->ptr == d->residual);
8393b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
8394b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    switchtobuf(d, buf, buf + size);
8395b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
8396b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8397b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  d->checkpoint = d->ptr;
8398b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8399b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Handle skips that don't cover the whole buffer (as above). */
8400b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (d->skip) {
8401b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    size_t skip_bytes = d->skip;
8402b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    d->skip = 0;
8403b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    CHECK_RETURN(skip(d, skip_bytes));
8404b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    checkpoint(d);
8405b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
8406b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8407b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* If we're inside an unknown group, continue to parse unknown values. */
8408b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (d->top->groupnum < 0) {
8409b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    CHECK_RETURN(upb_pbdecoder_skipunknown(d, -1, 0));
8410b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    checkpoint(d);
8411b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
8412b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8413b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return DECODE_OK;
8414b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
8415b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8416b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Suspends the decoder at the last checkpoint, without saving any residual
8417b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * bytes.  If there are any unconsumed bytes, returns a short byte count. */
8418b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammersize_t upb_pbdecoder_suspend(upb_pbdecoder *d) {
8419b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  d->pc = d->last;
8420b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (d->checkpoint == d->residual) {
8421b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Checkpoint was in residual buf; no user bytes were consumed. */
8422b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    d->ptr = d->residual;
8423b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return 0;
8424b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
8425b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    size_t ret = d->size_param - (d->end - d->checkpoint);
8426b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    assert(!in_residual_buf(d, d->checkpoint));
8427b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    assert(d->buf == d->buf_param || d->buf == &dummy_char);
8428b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8429b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    d->bufstart_ofs += (d->checkpoint - d->buf);
8430b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    d->residual_end = d->residual;
8431b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    switchtobuf(d, d->residual, d->residual_end);
8432b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return ret;
8433b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
8434b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
8435b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8436b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Suspends the decoder at the last checkpoint, and saves any unconsumed
8437b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * bytes in our residual buffer.  This is necessary if we need more user
8438b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * bytes to form a complete value, which might not be contiguous in the
8439b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * user's buffers.  Always consumes all user bytes. */
8440b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic size_t suspend_save(upb_pbdecoder *d) {
8441b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* We hit end-of-buffer before we could parse a full value.
8442b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * Save any unconsumed bytes (if any) to the residual buffer. */
8443b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  d->pc = d->last;
8444b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8445b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (d->checkpoint == d->residual) {
8446b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Checkpoint was in residual buf; append user byte(s) to residual buf. */
8447b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    assert((d->residual_end - d->residual) + d->size_param <=
8448b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer           sizeof(d->residual));
8449b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (!in_residual_buf(d, d->ptr)) {
8450b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      d->bufstart_ofs -= (d->residual_end - d->residual);
8451b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
8452b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    memcpy(d->residual_end, d->buf_param, d->size_param);
8453b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    d->residual_end += d->size_param;
8454b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
8455b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Checkpoint was in user buf; old residual bytes not needed. */
8456b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    size_t save;
8457b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    assert(!in_residual_buf(d, d->checkpoint));
8458b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8459b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    d->ptr = d->checkpoint;
8460b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    save = curbufleft(d);
8461b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    assert(save <= sizeof(d->residual));
8462b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    memcpy(d->residual, d->ptr, save);
8463b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    d->residual_end = d->residual + save;
8464b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    d->bufstart_ofs = offset(d);
8465b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
8466b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8467b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  switchtobuf(d, d->residual, d->residual_end);
8468b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return d->size_param;
8469b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
8470b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8471b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Copies the next "bytes" bytes into "buf" and advances the stream.
8472b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Requires that this many bytes are available in the current buffer. */
8473b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerUPB_FORCEINLINE static void consumebytes(upb_pbdecoder *d, void *buf,
8474b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                         size_t bytes) {
8475b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(bytes <= curbufleft(d));
8476b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  memcpy(buf, d->ptr, bytes);
8477b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  advance(d, bytes);
8478b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
8479b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8480b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Slow path for getting the next "bytes" bytes, regardless of whether they are
8481b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * available in the current buffer or not.  Returns a status code as described
8482b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * in decoder.int.h. */
8483b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerUPB_NOINLINE static int32_t getbytes_slow(upb_pbdecoder *d, void *buf,
8484b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                          size_t bytes) {
8485b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const size_t avail = curbufleft(d);
8486b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  consumebytes(d, buf, avail);
8487b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bytes -= avail;
8488b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(bytes > 0);
8489b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (in_residual_buf(d, d->ptr)) {
8490b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    advancetobuf(d, d->buf_param, d->size_param);
8491b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
8492b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (curbufleft(d) >= bytes) {
8493b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    consumebytes(d, (char *)buf + avail, bytes);
8494b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return DECODE_OK;
8495b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else if (d->data_end == d->delim_end) {
8496b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    seterr(d, "Submessage ended in the middle of a value or group");
8497b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return upb_pbdecoder_suspend(d);
8498b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
8499b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return suspend_save(d);
8500b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
8501b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
8502b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8503b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Gets the next "bytes" bytes, regardless of whether they are available in the
8504b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * current buffer or not.  Returns a status code as described in decoder.int.h.
8505b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */
8506b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerUPB_FORCEINLINE static int32_t getbytes(upb_pbdecoder *d, void *buf,
8507b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                        size_t bytes) {
8508b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (curbufleft(d) >= bytes) {
8509b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Buffer has enough data to satisfy. */
8510b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    consumebytes(d, buf, bytes);
8511b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return DECODE_OK;
8512b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
8513b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return getbytes_slow(d, buf, bytes);
8514b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
8515b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
8516b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8517b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerUPB_NOINLINE static size_t peekbytes_slow(upb_pbdecoder *d, void *buf,
8518b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                          size_t bytes) {
8519b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  size_t ret = curbufleft(d);
8520b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  memcpy(buf, d->ptr, ret);
8521b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (in_residual_buf(d, d->ptr)) {
8522b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    size_t copy = UPB_MIN(bytes - ret, d->size_param);
8523b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    memcpy((char *)buf + ret, d->buf_param, copy);
8524b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    ret += copy;
8525b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
8526b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return ret;
8527b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
8528b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8529b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerUPB_FORCEINLINE static size_t peekbytes(upb_pbdecoder *d, void *buf,
8530b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                        size_t bytes) {
8531b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (curbufleft(d) >= bytes) {
8532b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    memcpy(buf, d->ptr, bytes);
8533b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return bytes;
8534b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
8535b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return peekbytes_slow(d, buf, bytes);
8536b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
8537b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
8538b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8539b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8540b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Decoding of wire types *****************************************************/
8541b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8542b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Slow path for decoding a varint from the current buffer position.
8543b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Returns a status code as described in decoder.int.h. */
8544b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerUPB_NOINLINE int32_t upb_pbdecoder_decode_varint_slow(upb_pbdecoder *d,
8545b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                                      uint64_t *u64) {
8546b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  uint8_t byte = 0x80;
8547b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  int bitpos;
8548b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  *u64 = 0;
8549b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for(bitpos = 0; bitpos < 70 && (byte & 0x80); bitpos += 7) {
8550b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    CHECK_RETURN(getbytes(d, &byte, 1));
8551b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    *u64 |= (uint64_t)(byte & 0x7F) << bitpos;
8552b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
8553b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if(bitpos == 70 && (byte & 0x80)) {
8554b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    seterr(d, kUnterminatedVarint);
8555b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return upb_pbdecoder_suspend(d);
8556b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
8557b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return DECODE_OK;
8558b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
8559b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8560b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Decodes a varint from the current buffer position.
8561b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Returns a status code as described in decoder.int.h. */
8562b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerUPB_FORCEINLINE static int32_t decode_varint(upb_pbdecoder *d, uint64_t *u64) {
8563b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (curbufleft(d) > 0 && !(*d->ptr & 0x80)) {
8564b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    *u64 = *d->ptr;
8565b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    advance(d, 1);
8566b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return DECODE_OK;
8567b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else if (curbufleft(d) >= 10) {
8568b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Fast case. */
8569b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_decoderet r = upb_vdecode_fast(d->ptr);
8570b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (r.p == NULL) {
8571b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      seterr(d, kUnterminatedVarint);
8572b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return upb_pbdecoder_suspend(d);
8573b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
8574b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    advance(d, r.p - d->ptr);
8575b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    *u64 = r.val;
8576b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return DECODE_OK;
8577b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
8578b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Slow case -- varint spans buffer seam. */
8579b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return upb_pbdecoder_decode_varint_slow(d, u64);
8580b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
8581b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
8582b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8583b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Decodes a 32-bit varint from the current buffer position.
8584b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Returns a status code as described in decoder.int.h. */
8585b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerUPB_FORCEINLINE static int32_t decode_v32(upb_pbdecoder *d, uint32_t *u32) {
8586b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  uint64_t u64;
8587b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  int32_t ret = decode_varint(d, &u64);
8588b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (ret >= 0) return ret;
8589b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (u64 > UINT32_MAX) {
8590b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    seterr(d, "Unterminated 32-bit varint");
8591b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* TODO(haberman) guarantee that this function return is >= 0 somehow,
8592b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * so we know this path will always be treated as error by our caller.
8593b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * Right now the size_t -> int32_t can overflow and produce negative values.
8594b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     */
8595b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    *u32 = 0;
8596b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return upb_pbdecoder_suspend(d);
8597b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
8598b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  *u32 = u64;
8599b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return DECODE_OK;
8600b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
8601b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8602b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Decodes a fixed32 from the current buffer position.
8603b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Returns a status code as described in decoder.int.h.
8604b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * TODO: proper byte swapping for big-endian machines. */
8605b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerUPB_FORCEINLINE static int32_t decode_fixed32(upb_pbdecoder *d, uint32_t *u32) {
8606b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return getbytes(d, u32, 4);
8607b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
8608b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8609b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Decodes a fixed64 from the current buffer position.
8610b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Returns a status code as described in decoder.int.h.
8611b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * TODO: proper byte swapping for big-endian machines. */
8612b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerUPB_FORCEINLINE static int32_t decode_fixed64(upb_pbdecoder *d, uint64_t *u64) {
8613b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return getbytes(d, u64, 8);
8614b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
8615b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8616b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Non-static versions of the above functions.
8617b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * These are called by the JIT for fallback paths. */
8618b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerint32_t upb_pbdecoder_decode_f32(upb_pbdecoder *d, uint32_t *u32) {
8619b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return decode_fixed32(d, u32);
8620b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
8621b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8622b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerint32_t upb_pbdecoder_decode_f64(upb_pbdecoder *d, uint64_t *u64) {
8623b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return decode_fixed64(d, u64);
8624b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
8625b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8626b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic double as_double(uint64_t n) { double d; memcpy(&d, &n, 8); return d; }
8627b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic float  as_float(uint32_t n)  { float  f; memcpy(&f, &n, 4); return f; }
8628b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8629b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Pushes a frame onto the decoder stack. */
8630b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool decoder_push(upb_pbdecoder *d, uint64_t end) {
8631b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_pbdecoder_frame *fr = d->top;
8632b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8633b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (end > fr->end_ofs) {
8634b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    seterr(d, kPbDecoderSubmessageTooLong);
8635b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
8636b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else if (fr == d->limit) {
8637b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    seterr(d, kPbDecoderStackOverflow);
8638b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
8639b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
8640b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8641b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  fr++;
8642b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  fr->end_ofs = end;
8643b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  fr->dispatch = NULL;
8644b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  fr->groupnum = 0;
8645b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  d->top = fr;
8646b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
8647b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
8648b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8649b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool pushtagdelim(upb_pbdecoder *d, uint32_t arg) {
8650b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* While we expect to see an "end" tag (either ENDGROUP or a non-sequence
8651b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * field number) prior to hitting any enclosing submessage end, pushing our
8652b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * existing delim end prevents us from continuing to parse values from a
8653b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * corrupt proto that doesn't give us an END tag in time. */
8654b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!decoder_push(d, d->top->end_ofs))
8655b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
8656b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  d->top->groupnum = arg;
8657b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
8658b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
8659b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8660b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Pops a frame from the decoder stack. */
8661b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void decoder_pop(upb_pbdecoder *d) { d->top--; }
8662b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8663b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerUPB_NOINLINE int32_t upb_pbdecoder_checktag_slow(upb_pbdecoder *d,
8664b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                                 uint64_t expected) {
8665b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  uint64_t data = 0;
8666b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  size_t bytes = upb_value_size(expected);
8667b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  size_t read = peekbytes(d, &data, bytes);
8668b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (read == bytes && data == expected) {
8669b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Advance past matched bytes. */
8670b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    int32_t ok = getbytes(d, &data, read);
8671b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    UPB_ASSERT_VAR(ok, ok < 0);
8672b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return DECODE_OK;
8673b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else if (read < bytes && memcmp(&data, &expected, read) == 0) {
8674b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return suspend_save(d);
8675b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
8676b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return DECODE_MISMATCH;
8677b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
8678b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
8679b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8680b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerint32_t upb_pbdecoder_skipunknown(upb_pbdecoder *d, int32_t fieldnum,
8681b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                  uint8_t wire_type) {
8682b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (fieldnum >= 0)
8683b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    goto have_tag;
8684b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8685b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  while (true) {
8686b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    uint32_t tag;
8687b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    CHECK_RETURN(decode_v32(d, &tag));
8688b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    wire_type = tag & 0x7;
8689b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    fieldnum = tag >> 3;
8690b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8691b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerhave_tag:
8692b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (fieldnum == 0) {
8693b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      seterr(d, "Saw invalid field number (0)");
8694b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return upb_pbdecoder_suspend(d);
8695b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
8696b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8697b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* TODO: deliver to unknown field callback. */
8698b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    switch (wire_type) {
8699b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case UPB_WIRE_TYPE_32BIT:
8700b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        CHECK_RETURN(skip(d, 4));
8701b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        break;
8702b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case UPB_WIRE_TYPE_64BIT:
8703b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        CHECK_RETURN(skip(d, 8));
8704b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        break;
8705b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case UPB_WIRE_TYPE_VARINT: {
8706b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        uint64_t u64;
8707b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        CHECK_RETURN(decode_varint(d, &u64));
8708b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        break;
8709b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
8710b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case UPB_WIRE_TYPE_DELIMITED: {
8711b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        uint32_t len;
8712b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        CHECK_RETURN(decode_v32(d, &len));
8713b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        CHECK_RETURN(skip(d, len));
8714b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        break;
8715b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
8716b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case UPB_WIRE_TYPE_START_GROUP:
8717b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        CHECK_SUSPEND(pushtagdelim(d, -fieldnum));
8718b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        break;
8719b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case UPB_WIRE_TYPE_END_GROUP:
8720b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        if (fieldnum == -d->top->groupnum) {
8721b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          decoder_pop(d);
8722b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        } else if (fieldnum == d->top->groupnum) {
8723b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          return DECODE_ENDGROUP;
8724b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        } else {
8725b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          seterr(d, "Unmatched ENDGROUP tag.");
8726b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          return upb_pbdecoder_suspend(d);
8727b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        }
8728b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        break;
8729b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      default:
8730b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        seterr(d, "Invalid wire type");
8731b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        return upb_pbdecoder_suspend(d);
8732b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
8733b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8734b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (d->top->groupnum >= 0) {
8735b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return DECODE_OK;
8736b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
8737b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8738b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Unknown group -- continue looping over unknown fields. */
8739b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    checkpoint(d);
8740b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
8741b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
8742b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8743b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void goto_endmsg(upb_pbdecoder *d) {
8744b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_value v;
8745b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bool found = upb_inttable_lookup32(d->top->dispatch, DISPATCH_ENDMSG, &v);
8746b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_ASSERT_VAR(found, found);
8747b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  d->pc = d->top->base + upb_value_getuint64(v);
8748b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
8749b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8750b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Parses a tag and jumps to the corresponding bytecode instruction for this
8751b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * field.
8752b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *
8753b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * If the tag is unknown (or the wire type doesn't match), parses the field as
8754b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * unknown.  If the tag is a valid ENDGROUP tag, jumps to the bytecode
8755b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * instruction for the end of message. */
8756b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic int32_t dispatch(upb_pbdecoder *d) {
8757b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable *dispatch = d->top->dispatch;
8758b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  uint32_t tag;
8759b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  uint8_t wire_type;
8760b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  uint32_t fieldnum;
8761b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_value val;
8762b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  int32_t retval;
8763b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8764b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Decode tag. */
8765b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  CHECK_RETURN(decode_v32(d, &tag));
8766b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  wire_type = tag & 0x7;
8767b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  fieldnum = tag >> 3;
8768b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8769b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Lookup tag.  Because of packed/non-packed compatibility, we have to
8770b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * check the wire type against two possibilities. */
8771b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (fieldnum != DISPATCH_ENDMSG &&
8772b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_inttable_lookup32(dispatch, fieldnum, &val)) {
8773b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    uint64_t v = upb_value_getuint64(val);
8774b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (wire_type == (v & 0xff)) {
8775b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      d->pc = d->top->base + (v >> 16);
8776b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return DECODE_OK;
8777b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    } else if (wire_type == ((v >> 8) & 0xff)) {
8778b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      bool found =
8779b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          upb_inttable_lookup(dispatch, fieldnum + UPB_MAX_FIELDNUMBER, &val);
8780b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      UPB_ASSERT_VAR(found, found);
8781b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      d->pc = d->top->base + upb_value_getuint64(val);
8782b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return DECODE_OK;
8783b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
8784b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
8785b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8786b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* We have some unknown fields (or ENDGROUP) to parse.  The DISPATCH or TAG
8787b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * bytecode that triggered this is preceded by a CHECKDELIM bytecode which
8788b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * we need to back up to, so that when we're done skipping unknown data we
8789b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * can re-check the delimited end. */
8790b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  d->last--;  /* Necessary if we get suspended */
8791b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  d->pc = d->last;
8792b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(getop(*d->last) == OP_CHECKDELIM);
8793b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8794b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Unknown field or ENDGROUP. */
8795b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  retval = upb_pbdecoder_skipunknown(d, fieldnum, wire_type);
8796b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8797b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  CHECK_RETURN(retval);
8798b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8799b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (retval == DECODE_ENDGROUP) {
8800b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    goto_endmsg(d);
8801b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return DECODE_OK;
8802b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
8803b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8804b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return DECODE_OK;
8805b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
8806b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8807b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Callers know that the stack is more than one deep because the opcodes that
8808b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * call this only occur after PUSH operations. */
8809b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerupb_pbdecoder_frame *outer_frame(upb_pbdecoder *d) {
8810b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(d->top != d->stack);
8811b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return d->top - 1;
8812b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
8813b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8814b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8815b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* The main decoding loop *****************************************************/
8816b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8817b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* The main decoder VM function.  Uses traditional bytecode dispatch loop with a
8818b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * switch() statement. */
8819b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammersize_t run_decoder_vm(upb_pbdecoder *d, const mgroup *group,
8820b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                      const upb_bufhandle* handle) {
8821b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8822b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#define VMCASE(op, code) \
8823b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  case op: { code; if (consumes_input(op)) checkpoint(d); break; }
8824b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#define PRIMITIVE_OP(type, wt, name, convfunc, ctype) \
8825b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  VMCASE(OP_PARSE_ ## type, { \
8826b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    ctype val; \
8827b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    CHECK_RETURN(decode_ ## wt(d, &val)); \
8828b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_sink_put ## name(&d->top->sink, arg, (convfunc)(val)); \
8829b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  })
8830b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8831b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  while(1) {
8832b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    int32_t instruction;
8833b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    opcode op;
8834b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    uint32_t arg;
8835b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    int32_t longofs;
8836b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8837b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    d->last = d->pc;
8838b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    instruction = *d->pc++;
8839b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    op = getop(instruction);
8840b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    arg = instruction >> 8;
8841b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    longofs = arg;
8842b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    assert(d->ptr != d->residual_end);
8843b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    UPB_UNUSED(group);
8844b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#ifdef UPB_DUMP_BYTECODE
8845b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    fprintf(stderr, "s_ofs=%d buf_ofs=%d data_rem=%d buf_rem=%d delim_rem=%d "
8846b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                    "%x %s (%d)\n",
8847b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer            (int)offset(d),
8848b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer            (int)(d->ptr - d->buf),
8849b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer            (int)(d->data_end - d->ptr),
8850b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer            (int)(d->end - d->ptr),
8851b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer            (int)((d->top->end_ofs - d->bufstart_ofs) - (d->ptr - d->buf)),
8852b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer            (int)(d->pc - 1 - group->bytecode),
8853b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer            upb_pbdecoder_getopname(op),
8854b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer            arg);
8855b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#endif
8856b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    switch (op) {
8857b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      /* Technically, we are losing data if we see a 32-bit varint that is not
8858b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer       * properly sign-extended.  We could detect this and error about the data
8859b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer       * loss, but proto2 does not do this, so we pass. */
8860b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      PRIMITIVE_OP(INT32,    varint,  int32,  int32_t,      uint64_t)
8861b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      PRIMITIVE_OP(INT64,    varint,  int64,  int64_t,      uint64_t)
8862b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      PRIMITIVE_OP(UINT32,   varint,  uint32, uint32_t,     uint64_t)
8863b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      PRIMITIVE_OP(UINT64,   varint,  uint64, uint64_t,     uint64_t)
8864b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      PRIMITIVE_OP(FIXED32,  fixed32, uint32, uint32_t,     uint32_t)
8865b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      PRIMITIVE_OP(FIXED64,  fixed64, uint64, uint64_t,     uint64_t)
8866b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      PRIMITIVE_OP(SFIXED32, fixed32, int32,  int32_t,      uint32_t)
8867b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      PRIMITIVE_OP(SFIXED64, fixed64, int64,  int64_t,      uint64_t)
8868b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      PRIMITIVE_OP(BOOL,     varint,  bool,   bool,         uint64_t)
8869b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      PRIMITIVE_OP(DOUBLE,   fixed64, double, as_double,    uint64_t)
8870b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      PRIMITIVE_OP(FLOAT,    fixed32, float,  as_float,     uint32_t)
8871b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      PRIMITIVE_OP(SINT32,   varint,  int32,  upb_zzdec_32, uint64_t)
8872b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      PRIMITIVE_OP(SINT64,   varint,  int64,  upb_zzdec_64, uint64_t)
8873b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
8874b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      VMCASE(OP_SETDISPATCH,
8875b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        d->top->base = d->pc - 1;
8876b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        memcpy(&d->top->dispatch, d->pc, sizeof(void*));
8877b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        d->pc += sizeof(void*) / sizeof(uint32_t);
8878b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      )
8879b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      VMCASE(OP_STARTMSG,
8880b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        CHECK_SUSPEND(upb_sink_startmsg(&d->top->sink));
8881b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      )
8882b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      VMCASE(OP_ENDMSG,
8883b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        CHECK_SUSPEND(upb_sink_endmsg(&d->top->sink, d->status));
8884b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      )
8885b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      VMCASE(OP_STARTSEQ,
8886b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_pbdecoder_frame *outer = outer_frame(d);
8887b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        CHECK_SUSPEND(upb_sink_startseq(&outer->sink, arg, &d->top->sink));
8888b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      )
8889b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      VMCASE(OP_ENDSEQ,
8890b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        CHECK_SUSPEND(upb_sink_endseq(&d->top->sink, arg));
8891b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      )
8892b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      VMCASE(OP_STARTSUBMSG,
8893b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_pbdecoder_frame *outer = outer_frame(d);
8894b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        CHECK_SUSPEND(upb_sink_startsubmsg(&outer->sink, arg, &d->top->sink));
8895b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      )
8896b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      VMCASE(OP_ENDSUBMSG,
8897b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        CHECK_SUSPEND(upb_sink_endsubmsg(&d->top->sink, arg));
8898b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      )
8899b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      VMCASE(OP_STARTSTR,
8900b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        uint32_t len = delim_remaining(d);
8901b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_pbdecoder_frame *outer = outer_frame(d);
8902b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        CHECK_SUSPEND(upb_sink_startstr(&outer->sink, arg, len, &d->top->sink));
8903b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        if (len == 0) {
8904b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          d->pc++;  /* Skip OP_STRING. */
8905b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        }
8906b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      )
8907b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      VMCASE(OP_STRING,
8908b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        uint32_t len = curbufleft(d);
8909b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        size_t n = upb_sink_putstring(&d->top->sink, arg, d->ptr, len, handle);
8910b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        if (n > len) {
8911b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          if (n > delim_remaining(d)) {
8912b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer            seterr(d, "Tried to skip past end of string.");
8913b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer            return upb_pbdecoder_suspend(d);
8914b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          } else {
8915b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer            int32_t ret = skip(d, n);
8916b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer            /* This shouldn't return DECODE_OK, because n > len. */
8917b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer            assert(ret >= 0);
8918b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer            return ret;
8919b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          }
8920b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        }
8921b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        advance(d, n);
8922b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        if (n < len || d->delim_end == NULL) {
8923b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          /* We aren't finished with this string yet. */
8924b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          d->pc--;  /* Repeat OP_STRING. */
8925b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          if (n > 0) checkpoint(d);
8926b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          return upb_pbdecoder_suspend(d);
8927b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        }
8928b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      )
8929b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      VMCASE(OP_ENDSTR,
8930b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        CHECK_SUSPEND(upb_sink_endstr(&d->top->sink, arg));
8931b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      )
8932b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      VMCASE(OP_PUSHTAGDELIM,
8933b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        CHECK_SUSPEND(pushtagdelim(d, arg));
8934b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      )
8935b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      VMCASE(OP_SETBIGGROUPNUM,
8936b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        d->top->groupnum = *d->pc++;
8937b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      )
8938b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      VMCASE(OP_POP,
8939b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        assert(d->top > d->stack);
8940b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        decoder_pop(d);
8941b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      )
8942b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      VMCASE(OP_PUSHLENDELIM,
8943b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        uint32_t len;
8944b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        CHECK_RETURN(decode_v32(d, &len));
8945b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        CHECK_SUSPEND(decoder_push(d, offset(d) + len));
8946b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        set_delim_end(d);
8947b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      )
8948b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      VMCASE(OP_SETDELIM,
8949b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        set_delim_end(d);
8950b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      )
8951b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      VMCASE(OP_CHECKDELIM,
8952b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        /* We are guaranteed of this assert because we never allow ourselves to
8953b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer         * consume bytes beyond data_end, which covers delim_end when non-NULL.
8954b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer         */
8955b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        assert(!(d->delim_end && d->ptr > d->delim_end));
8956b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        if (d->ptr == d->delim_end)
8957b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          d->pc += longofs;
8958b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      )
8959b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      VMCASE(OP_CALL,
8960b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        d->callstack[d->call_len++] = d->pc;
8961b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        d->pc += longofs;
8962b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      )
8963b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      VMCASE(OP_RET,
8964b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        assert(d->call_len > 0);
8965b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        d->pc = d->callstack[--d->call_len];
8966b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      )
8967b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      VMCASE(OP_BRANCH,
8968b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        d->pc += longofs;
8969b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      )
8970b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      VMCASE(OP_TAG1,
8971b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        uint8_t expected;
8972b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        CHECK_SUSPEND(curbufleft(d) > 0);
8973b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        expected = (arg >> 8) & 0xff;
8974b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        if (*d->ptr == expected) {
8975b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          advance(d, 1);
8976b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        } else {
8977b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          int8_t shortofs;
8978b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer         badtag:
8979b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          shortofs = arg;
8980b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          if (shortofs == LABEL_DISPATCH) {
8981b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer            CHECK_RETURN(dispatch(d));
8982b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          } else {
8983b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer            d->pc += shortofs;
8984b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer            break; /* Avoid checkpoint(). */
8985b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          }
8986b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        }
8987b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      )
8988b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      VMCASE(OP_TAG2,
8989b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        uint16_t expected;
8990b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        CHECK_SUSPEND(curbufleft(d) > 0);
8991b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        expected = (arg >> 8) & 0xffff;
8992b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        if (curbufleft(d) >= 2) {
8993b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          uint16_t actual;
8994b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          memcpy(&actual, d->ptr, 2);
8995b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          if (expected == actual) {
8996b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer            advance(d, 2);
8997b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          } else {
8998b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer            goto badtag;
8999b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          }
9000b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        } else {
9001b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          int32_t result = upb_pbdecoder_checktag_slow(d, expected);
9002b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          if (result == DECODE_MISMATCH) goto badtag;
9003b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          if (result >= 0) return result;
9004b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        }
9005b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      )
9006b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      VMCASE(OP_TAGN, {
9007b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        uint64_t expected;
9008b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        int32_t result;
9009b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        memcpy(&expected, d->pc, 8);
9010b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        d->pc += 2;
9011b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        result = upb_pbdecoder_checktag_slow(d, expected);
9012b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        if (result == DECODE_MISMATCH) goto badtag;
9013b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        if (result >= 0) return result;
9014b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      })
9015b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      VMCASE(OP_DISPATCH, {
9016b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        CHECK_RETURN(dispatch(d));
9017b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      })
9018b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      VMCASE(OP_HALT, {
9019b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        return d->size_param;
9020b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      })
9021b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
9022b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
9023b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
9024b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9025b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9026b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* BytesHandler handlers ******************************************************/
9027b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9028b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid *upb_pbdecoder_startbc(void *closure, const void *pc, size_t size_hint) {
9029b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_pbdecoder *d = closure;
9030b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(size_hint);
9031b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  d->top->end_ofs = UINT64_MAX;
9032b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  d->bufstart_ofs = 0;
9033b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  d->call_len = 1;
9034b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  d->callstack[0] = &halt;
9035b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  d->pc = pc;
9036b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  d->skip = 0;
9037b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return d;
9038b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
9039b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9040b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid *upb_pbdecoder_startjit(void *closure, const void *hd, size_t size_hint) {
9041b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_pbdecoder *d = closure;
9042b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(hd);
9043b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(size_hint);
9044b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  d->top->end_ofs = UINT64_MAX;
9045b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  d->bufstart_ofs = 0;
9046b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  d->call_len = 0;
9047b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  d->skip = 0;
9048b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return d;
9049b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
9050b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9051b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_pbdecoder_end(void *closure, const void *handler_data) {
9052b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_pbdecoder *d = closure;
9053b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const upb_pbdecodermethod *method = handler_data;
9054b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  uint64_t end;
9055b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  char dummy;
9056b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9057b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (d->residual_end > d->residual) {
9058b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    seterr(d, "Unexpected EOF: decoder still has buffered unparsed data");
9059b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
9060b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
9061b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9062b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (d->skip) {
9063b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    seterr(d, "Unexpected EOF inside skipped data");
9064b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
9065b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
9066b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9067b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (d->top->end_ofs != UINT64_MAX) {
9068b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    seterr(d, "Unexpected EOF inside delimited string");
9069b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
9070b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
9071b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9072b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* The user's end() call indicates that the message ends here. */
9073b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  end = offset(d);
9074b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  d->top->end_ofs = end;
9075b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9076b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#ifdef UPB_USE_JIT_X64
9077b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (method->is_native_) {
9078b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    const mgroup *group = (const mgroup*)method->group;
9079b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (d->top != d->stack)
9080b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      d->stack->end_ofs = 0;
9081b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    group->jit_code(closure, method->code_base.ptr, &dummy, 0, NULL);
9082b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else
9083b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#endif
9084b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  {
9085b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    const uint32_t *p = d->pc;
9086b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    d->stack->end_ofs = end;
9087b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Check the previous bytecode, but guard against beginning. */
9088b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (p != method->code_base.ptr) p--;
9089b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (getop(*p) == OP_CHECKDELIM) {
9090b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      /* Rewind from OP_TAG* to OP_CHECKDELIM. */
9091b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      assert(getop(*d->pc) == OP_TAG1 ||
9092b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer             getop(*d->pc) == OP_TAG2 ||
9093b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer             getop(*d->pc) == OP_TAGN ||
9094b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer             getop(*d->pc) == OP_DISPATCH);
9095b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      d->pc = p;
9096b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
9097b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_pbdecoder_decode(closure, handler_data, &dummy, 0, NULL);
9098b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
9099b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9100b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (d->call_len != 0) {
9101b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    seterr(d, "Unexpected EOF inside submessage or group");
9102b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
9103b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
9104b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9105b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
9106b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
9107b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9108b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammersize_t upb_pbdecoder_decode(void *decoder, const void *group, const char *buf,
9109b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                            size_t size, const upb_bufhandle *handle) {
9110b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  int32_t result = upb_pbdecoder_resume(decoder, NULL, buf, size, handle);
9111b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9112b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (result == DECODE_ENDGROUP) goto_endmsg(decoder);
9113b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  CHECK_RETURN(result);
9114b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9115b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return run_decoder_vm(decoder, group, handle);
9116b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
9117b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9118b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9119b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Public API *****************************************************************/
9120b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9121b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_pbdecoder_reset(upb_pbdecoder *d) {
9122b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  d->top = d->stack;
9123b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  d->top->groupnum = 0;
9124b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  d->ptr = d->residual;
9125b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  d->buf = d->residual;
9126b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  d->end = d->residual;
9127b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  d->residual_end = d->residual;
9128b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
9129b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9130b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerupb_pbdecoder *upb_pbdecoder_create(upb_env *e, const upb_pbdecodermethod *m,
9131b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                    upb_sink *sink) {
9132b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const size_t default_max_nesting = 64;
9133b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#ifndef NDEBUG
9134b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  size_t size_before = upb_env_bytesallocated(e);
9135b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#endif
9136b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9137b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_pbdecoder *d = upb_env_malloc(e, sizeof(upb_pbdecoder));
9138b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!d) return NULL;
9139b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9140b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  d->method_ = m;
9141b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  d->callstack = upb_env_malloc(e, callstacksize(d, default_max_nesting));
9142b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  d->stack = upb_env_malloc(e, stacksize(d, default_max_nesting));
9143b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!d->stack || !d->callstack) {
9144b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return NULL;
9145b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
9146b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9147b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  d->env = e;
9148b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  d->limit = d->stack + default_max_nesting - 1;
9149b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  d->stack_size = default_max_nesting;
9150b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  d->status = NULL;
9151b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9152b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_pbdecoder_reset(d);
9153b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_bytessink_reset(&d->input_, &m->input_handler_, d);
9154b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9155b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(sink);
9156b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (d->method_->dest_handlers_) {
9157b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (sink->handlers != d->method_->dest_handlers_)
9158b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return NULL;
9159b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
9160b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_sink_reset(&d->top->sink, sink->handlers, sink->closure);
9161b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9162b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* If this fails, increase the value in decoder.h. */
9163b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(upb_env_bytesallocated(e) - size_before <= UPB_PB_DECODER_SIZE);
9164b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return d;
9165b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
9166b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9167b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammeruint64_t upb_pbdecoder_bytesparsed(const upb_pbdecoder *d) {
9168b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return offset(d);
9169b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
9170b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9171b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_pbdecodermethod *upb_pbdecoder_method(const upb_pbdecoder *d) {
9172b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return d->method_;
9173b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
9174b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9175b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerupb_bytessink *upb_pbdecoder_input(upb_pbdecoder *d) {
9176b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return &d->input_;
9177b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
9178b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9179b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammersize_t upb_pbdecoder_maxnesting(const upb_pbdecoder *d) {
9180b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return d->stack_size;
9181b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
9182b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9183b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool upb_pbdecoder_setmaxnesting(upb_pbdecoder *d, size_t max) {
9184b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(d->top >= d->stack);
9185b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9186b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (max < (size_t)(d->top - d->stack)) {
9187b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Can't set a limit smaller than what we are currently at. */
9188b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
9189b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
9190b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9191b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (max > d->stack_size) {
9192b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Need to reallocate stack and callstack to accommodate. */
9193b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    size_t old_size = stacksize(d, d->stack_size);
9194b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    size_t new_size = stacksize(d, max);
9195b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    void *p = upb_env_realloc(d->env, d->stack, old_size, new_size);
9196b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (!p) {
9197b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return false;
9198b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
9199b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    d->stack = p;
9200b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9201b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    old_size = callstacksize(d, d->stack_size);
9202b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    new_size = callstacksize(d, max);
9203b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    p = upb_env_realloc(d->env, d->callstack, old_size, new_size);
9204b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (!p) {
9205b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return false;
9206b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
9207b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    d->callstack = p;
9208b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9209b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    d->stack_size = max;
9210b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
9211b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9212b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  d->limit = d->stack + max - 1;
9213b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
9214b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
9215b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/*
9216b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** upb::Encoder
9217b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer**
9218b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** Since we are implementing pure handlers (ie. without any out-of-band access
9219b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** to pre-computed lengths), we have to buffer all submessages before we can
9220b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** emit even their first byte.
9221b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer**
9222b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** Not knowing the size of submessages also means we can't write a perfect
9223b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** zero-copy implementation, even with buffering.  Lengths are stored as
9224b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** varints, which means that we don't know how many bytes to reserve for the
9225b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** length until we know what the length is.
9226b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer**
9227b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** This leaves us with three main choices:
9228b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer**
9229b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** 1. buffer all submessage data in a temporary buffer, then copy it exactly
9230b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer**    once into the output buffer.
9231b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer**
9232b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** 2. attempt to buffer data directly into the output buffer, estimating how
9233b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer**    many bytes each length will take.  When our guesses are wrong, use
9234b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer**    memmove() to grow or shrink the allotted space.
9235b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer**
9236b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** 3. buffer directly into the output buffer, allocating a max length
9237b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer**    ahead-of-time for each submessage length.  If we overallocated, we waste
9238b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer**    space, but no memcpy() or memmove() is required.  This approach requires
9239b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer**    defining a maximum size for submessages and rejecting submessages that
9240b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer**    exceed that size.
9241b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer**
9242b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** (2) and (3) have the potential to have better performance, but they are more
9243b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** complicated and subtle to implement:
9244b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer**
9245b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer**   (3) requires making an arbitrary choice of the maximum message size; it
9246b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer**       wastes space when submessages are shorter than this and fails
9247b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer**       completely when they are longer.  This makes it more finicky and
9248b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer**       requires configuration based on the input.  It also makes it impossible
9249b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer**       to perfectly match the output of reference encoders that always use the
9250b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer**       optimal amount of space for each length.
9251b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer**
9252b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer**   (2) requires guessing the the size upfront, and if multiple lengths are
9253b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer**       guessed wrong the minimum required number of memmove() operations may
9254b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer**       be complicated to compute correctly.  Implemented properly, it may have
9255b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer**       a useful amortized or average cost, but more investigation is required
9256b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer**       to determine this and what the optimal algorithm is to achieve it.
9257b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer**
9258b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer**   (1) makes you always pay for exactly one copy, but its implementation is
9259b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer**       the simplest and its performance is predictable.
9260b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer**
9261b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** So for now, we implement (1) only.  If we wish to optimize later, we should
9262b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** be able to do it without affecting users.
9263b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer**
9264b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** The strategy is to buffer the segments of data that do *not* depend on
9265b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** unknown lengths in one buffer, and keep a separate buffer of segment pointers
9266b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** and lengths.  When the top-level submessage ends, we can go beginning to end,
9267b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** alternating the writing of lengths with memcpy() of the rest of the data.
9268b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** At the top level though, no buffering is required.
9269b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer*/
9270b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9271b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9272b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9273b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* The output buffer is divided into segments; a segment is a string of data
9274b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * that is "ready to go" -- it does not need any varint lengths inserted into
9275b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * the middle.  The seams between segments are where varints will be inserted
9276b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * once they are known.
9277b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *
9278b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * We also use the concept of a "run", which is a range of encoded bytes that
9279b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * occur at a single submessage level.  Every segment contains one or more runs.
9280b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *
9281b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * A segment can span messages.  Consider:
9282b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *
9283b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *                  .--Submessage lengths---------.
9284b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *                  |       |                     |
9285b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *                  |       V                     V
9286b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *                  V      | |---------------    | |-----------------
9287b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Submessages:    | |-----------------------------------------------
9288b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Top-level msg: ------------------------------------------------------------
9289b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *
9290b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Segments:          -----   -------------------   -----------------
9291b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Runs:              *----   *--------------*---   *----------------
9292b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * (* marks the start)
9293b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *
9294b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Note that the top-level menssage is not in any segment because it does not
9295b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * have any length preceding it.
9296b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *
9297b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * A segment is only interrupted when another length needs to be inserted.  So
9298b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * observe how the second segment spans both the inner submessage and part of
9299b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * the next enclosing message. */
9300b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammertypedef struct {
9301b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  uint32_t msglen;  /* The length to varint-encode before this segment. */
9302b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  uint32_t seglen;  /* Length of the segment. */
9303b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer} upb_pb_encoder_segment;
9304b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9305b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstruct upb_pb_encoder {
9306b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_env *env;
9307b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9308b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Our input and output. */
9309b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_sink input_;
9310b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_bytessink *output_;
9311b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9312b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* The "subclosure" -- used as the inner closure as part of the bytessink
9313b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * protocol. */
9314b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  void *subc;
9315b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9316b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* The output buffer and limit, and our current write position.  "buf"
9317b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * initially points to "initbuf", but is dynamically allocated if we need to
9318b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * grow beyond the initial size. */
9319b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  char *buf, *ptr, *limit;
9320b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9321b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* The beginning of the current run, or undefined if we are at the top
9322b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * level. */
9323b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  char *runbegin;
9324b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9325b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* The list of segments we are accumulating. */
9326b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_pb_encoder_segment *segbuf, *segptr, *seglimit;
9327b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9328b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* The stack of enclosing submessages.  Each entry in the stack points to the
9329b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * segment where this submessage's length is being accumulated. */
9330b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  int *stack, *top, *stacklimit;
9331b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9332b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Depth of startmsg/endmsg calls. */
9333b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  int depth;
9334b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer};
9335b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9336b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* low-level buffering ********************************************************/
9337b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9338b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Low-level functions for interacting with the output buffer. */
9339b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9340b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* TODO(haberman): handle pushback */
9341b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void putbuf(upb_pb_encoder *e, const char *buf, size_t len) {
9342b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  size_t n = upb_bytessink_putbuf(e->output_, e->subc, buf, len, NULL);
9343b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_ASSERT_VAR(n, n == len);
9344b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
9345b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9346b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic upb_pb_encoder_segment *top(upb_pb_encoder *e) {
9347b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return &e->segbuf[*e->top];
9348b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
9349b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9350b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Call to ensure that at least "bytes" bytes are available for writing at
9351b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * e->ptr.  Returns false if the bytes could not be allocated. */
9352b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool reserve(upb_pb_encoder *e, size_t bytes) {
9353b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if ((size_t)(e->limit - e->ptr) < bytes) {
9354b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Grow buffer. */
9355b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    char *new_buf;
9356b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    size_t needed = bytes + (e->ptr - e->buf);
9357b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    size_t old_size = e->limit - e->buf;
9358b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9359b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    size_t new_size = old_size;
9360b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9361b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    while (new_size < needed) {
9362b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      new_size *= 2;
9363b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
9364b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9365b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    new_buf = upb_env_realloc(e->env, e->buf, old_size, new_size);
9366b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9367b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (new_buf == NULL) {
9368b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return false;
9369b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
9370b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9371b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    e->ptr = new_buf + (e->ptr - e->buf);
9372b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    e->runbegin = new_buf + (e->runbegin - e->buf);
9373b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    e->limit = new_buf + new_size;
9374b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    e->buf = new_buf;
9375b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
9376b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9377b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
9378b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
9379b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9380b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Call when "bytes" bytes have been writte at e->ptr.  The caller *must* have
9381b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * previously called reserve() with at least this many bytes. */
9382b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void encoder_advance(upb_pb_encoder *e, size_t bytes) {
9383b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert((size_t)(e->limit - e->ptr) >= bytes);
9384b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  e->ptr += bytes;
9385b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
9386b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9387b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Call when all of the bytes for a handler have been written.  Flushes the
9388b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * bytes if possible and necessary, returning false if this failed. */
9389b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool commit(upb_pb_encoder *e) {
9390b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!e->top) {
9391b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* We aren't inside a delimited region.  Flush our accumulated bytes to
9392b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * the output.
9393b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     *
9394b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * TODO(haberman): in the future we may want to delay flushing for
9395b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * efficiency reasons. */
9396b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putbuf(e, e->buf, e->ptr - e->buf);
9397b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    e->ptr = e->buf;
9398b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
9399b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9400b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
9401b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
9402b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9403b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Writes the given bytes to the buffer, handling reserve/advance. */
9404b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool encode_bytes(upb_pb_encoder *e, const void *data, size_t len) {
9405b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!reserve(e, len)) {
9406b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
9407b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
9408b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9409b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  memcpy(e->ptr, data, len);
9410b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  encoder_advance(e, len);
9411b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
9412b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
9413b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9414b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Finish the current run by adding the run totals to the segment and message
9415b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * length. */
9416b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void accumulate(upb_pb_encoder *e) {
9417b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  size_t run_len;
9418b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(e->ptr >= e->runbegin);
9419b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  run_len = e->ptr - e->runbegin;
9420b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  e->segptr->seglen += run_len;
9421b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  top(e)->msglen += run_len;
9422b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  e->runbegin = e->ptr;
9423b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
9424b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9425b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Call to indicate the start of delimited region for which the full length is
9426b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * not yet known.  All data will be buffered until the length is known.
9427b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Delimited regions may be nested; their lengths will all be tracked properly. */
9428b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool start_delim(upb_pb_encoder *e) {
9429b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (e->top) {
9430b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* We are already buffering, advance to the next segment and push it on the
9431b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * stack. */
9432b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    accumulate(e);
9433b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9434b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (++e->top == e->stacklimit) {
9435b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      /* TODO(haberman): grow stack? */
9436b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return false;
9437b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
9438b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9439b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (++e->segptr == e->seglimit) {
9440b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      /* Grow segment buffer. */
9441b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      size_t old_size =
9442b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          (e->seglimit - e->segbuf) * sizeof(upb_pb_encoder_segment);
9443b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      size_t new_size = old_size * 2;
9444b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_pb_encoder_segment *new_buf =
9445b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          upb_env_realloc(e->env, e->segbuf, old_size, new_size);
9446b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9447b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (new_buf == NULL) {
9448b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        return false;
9449b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
9450b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9451b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      e->segptr = new_buf + (e->segptr - e->segbuf);
9452b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      e->seglimit = new_buf + (new_size / sizeof(upb_pb_encoder_segment));
9453b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      e->segbuf = new_buf;
9454b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
9455b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
9456b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* We were previously at the top level, start buffering. */
9457b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    e->segptr = e->segbuf;
9458b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    e->top = e->stack;
9459b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    e->runbegin = e->ptr;
9460b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
9461b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9462b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  *e->top = e->segptr - e->segbuf;
9463b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  e->segptr->seglen = 0;
9464b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  e->segptr->msglen = 0;
9465b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9466b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
9467b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
9468b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9469b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Call to indicate the end of a delimited region.  We now know the length of
9470b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * the delimited region.  If we are not nested inside any other delimited
9471b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * regions, we can now emit all of the buffered data we accumulated. */
9472b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool end_delim(upb_pb_encoder *e) {
9473b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  size_t msglen;
9474b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  accumulate(e);
9475b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  msglen = top(e)->msglen;
9476b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9477b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (e->top == e->stack) {
9478b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* All lengths are now available, emit all buffered data. */
9479b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    char buf[UPB_PB_VARINT_MAX_LEN];
9480b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_pb_encoder_segment *s;
9481b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    const char *ptr = e->buf;
9482b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    for (s = e->segbuf; s <= e->segptr; s++) {
9483b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      size_t lenbytes = upb_vencode64(s->msglen, buf);
9484b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      putbuf(e, buf, lenbytes);
9485b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      putbuf(e, ptr, s->seglen);
9486b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      ptr += s->seglen;
9487b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
9488b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9489b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    e->ptr = e->buf;
9490b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    e->top = NULL;
9491b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
9492b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Need to keep buffering; propagate length info into enclosing
9493b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * submessages. */
9494b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    --e->top;
9495b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    top(e)->msglen += msglen + upb_varint_size(msglen);
9496b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
9497b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9498b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
9499b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
9500b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9501b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9502b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* tag_t **********************************************************************/
9503b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9504b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* A precomputed (pre-encoded) tag and length. */
9505b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9506b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammertypedef struct {
9507b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  uint8_t bytes;
9508b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  char tag[7];
9509b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer} tag_t;
9510b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9511b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Allocates a new tag for this field, and sets it in these handlerattr. */
9512b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void new_tag(upb_handlers *h, const upb_fielddef *f, upb_wiretype_t wt,
9513b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                    upb_handlerattr *attr) {
9514b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  uint32_t n = upb_fielddef_number(f);
9515b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9516b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  tag_t *tag = upb_gmalloc(sizeof(tag_t));
9517b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  tag->bytes = upb_vencode64((n << 3) | wt, tag->tag);
9518b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9519b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_handlerattr_init(attr);
9520b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_handlerattr_sethandlerdata(attr, tag);
9521b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_handlers_addcleanup(h, tag, upb_gfree);
9522b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
9523b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9524b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool encode_tag(upb_pb_encoder *e, const tag_t *tag) {
9525b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return encode_bytes(e, tag->tag, tag->bytes);
9526b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
9527b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9528b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9529b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* encoding of wire types *****************************************************/
9530b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9531b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool encode_fixed64(upb_pb_encoder *e, uint64_t val) {
9532b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* TODO(haberman): byte-swap for big endian. */
9533b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return encode_bytes(e, &val, sizeof(uint64_t));
9534b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
9535b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9536b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool encode_fixed32(upb_pb_encoder *e, uint32_t val) {
9537b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* TODO(haberman): byte-swap for big endian. */
9538b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return encode_bytes(e, &val, sizeof(uint32_t));
9539b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
9540b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9541b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool encode_varint(upb_pb_encoder *e, uint64_t val) {
9542b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!reserve(e, UPB_PB_VARINT_MAX_LEN)) {
9543b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
9544b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
9545b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9546b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  encoder_advance(e, upb_vencode64(val, e->ptr));
9547b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
9548b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
9549b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9550b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic uint64_t dbl2uint64(double d) {
9551b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  uint64_t ret;
9552b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  memcpy(&ret, &d, sizeof(uint64_t));
9553b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return ret;
9554b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
9555b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9556b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic uint32_t flt2uint32(float d) {
9557b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  uint32_t ret;
9558b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  memcpy(&ret, &d, sizeof(uint32_t));
9559b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return ret;
9560b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
9561b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9562b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9563b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* encoding of proto types ****************************************************/
9564b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9565b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool startmsg(void *c, const void *hd) {
9566b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_pb_encoder *e = c;
9567b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(hd);
9568b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (e->depth++ == 0) {
9569b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_bytessink_start(e->output_, 0, &e->subc);
9570b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
9571b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
9572b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
9573b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9574b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool endmsg(void *c, const void *hd, upb_status *status) {
9575b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_pb_encoder *e = c;
9576b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(hd);
9577b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(status);
9578b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (--e->depth == 0) {
9579b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_bytessink_end(e->output_);
9580b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
9581b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
9582b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
9583b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9584b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void *encode_startdelimfield(void *c, const void *hd) {
9585b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bool ok = encode_tag(c, hd) && commit(c) && start_delim(c);
9586b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return ok ? c : UPB_BREAK;
9587b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
9588b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9589b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool encode_enddelimfield(void *c, const void *hd) {
9590b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(hd);
9591b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return end_delim(c);
9592b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
9593b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9594b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void *encode_startgroup(void *c, const void *hd) {
9595b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return (encode_tag(c, hd) && commit(c)) ? c : UPB_BREAK;
9596b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
9597b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9598b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool encode_endgroup(void *c, const void *hd) {
9599b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return encode_tag(c, hd) && commit(c);
9600b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
9601b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9602b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void *encode_startstr(void *c, const void *hd, size_t size_hint) {
9603b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(size_hint);
9604b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return encode_startdelimfield(c, hd);
9605b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
9606b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9607b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic size_t encode_strbuf(void *c, const void *hd, const char *buf,
9608b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                            size_t len, const upb_bufhandle *h) {
9609b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(hd);
9610b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(h);
9611b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return encode_bytes(c, buf, len) ? len : 0;
9612b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
9613b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9614b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#define T(type, ctype, convert, encode)                                  \
9615b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  static bool encode_scalar_##type(void *e, const void *hd, ctype val) { \
9616b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return encode_tag(e, hd) && encode(e, (convert)(val)) && commit(e);  \
9617b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }                                                                      \
9618b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  static bool encode_packed_##type(void *e, const void *hd, ctype val) { \
9619b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    UPB_UNUSED(hd);                                                      \
9620b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return encode(e, (convert)(val));                                    \
9621b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
9622b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9623b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerT(double,   double,   dbl2uint64,   encode_fixed64)
9624b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerT(float,    float,    flt2uint32,   encode_fixed32)
9625b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerT(int64,    int64_t,  uint64_t,     encode_varint)
9626b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerT(int32,    int32_t,  uint32_t,     encode_varint)
9627b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerT(fixed64,  uint64_t, uint64_t,     encode_fixed64)
9628b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerT(fixed32,  uint32_t, uint32_t,     encode_fixed32)
9629b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerT(bool,     bool,     bool,         encode_varint)
9630b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerT(uint32,   uint32_t, uint32_t,     encode_varint)
9631b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerT(uint64,   uint64_t, uint64_t,     encode_varint)
9632b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerT(enum,     int32_t,  uint32_t,     encode_varint)
9633b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerT(sfixed32, int32_t,  uint32_t,     encode_fixed32)
9634b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerT(sfixed64, int64_t,  uint64_t,     encode_fixed64)
9635b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerT(sint32,   int32_t,  upb_zzenc_32, encode_varint)
9636b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerT(sint64,   int64_t,  upb_zzenc_64, encode_varint)
9637b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9638b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#undef T
9639b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9640b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9641b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* code to build the handlers *************************************************/
9642b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9643b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void newhandlers_callback(const void *closure, upb_handlers *h) {
9644b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const upb_msgdef *m;
9645b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_msg_field_iter i;
9646b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9647b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(closure);
9648b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9649b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_handlers_setstartmsg(h, startmsg, NULL);
9650b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_handlers_setendmsg(h, endmsg, NULL);
9651b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9652b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  m = upb_handlers_msgdef(h);
9653b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for(upb_msg_field_begin(&i, m);
9654b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      !upb_msg_field_done(&i);
9655b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_msg_field_next(&i)) {
9656b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    const upb_fielddef *f = upb_msg_iter_field(&i);
9657b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    bool packed = upb_fielddef_isseq(f) && upb_fielddef_isprimitive(f) &&
9658b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                  upb_fielddef_packed(f);
9659b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_handlerattr attr;
9660b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_wiretype_t wt =
9661b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        packed ? UPB_WIRE_TYPE_DELIMITED
9662b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer               : upb_pb_native_wire_types[upb_fielddef_descriptortype(f)];
9663b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9664b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Pre-encode the tag for this field. */
9665b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    new_tag(h, f, wt, &attr);
9666b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9667b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (packed) {
9668b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_handlers_setstartseq(h, f, encode_startdelimfield, &attr);
9669b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_handlers_setendseq(h, f, encode_enddelimfield, &attr);
9670b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
9671b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9672b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#define T(upper, lower, upbtype)                                     \
9673b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  case UPB_DESCRIPTOR_TYPE_##upper:                                  \
9674b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (packed) {                                                    \
9675b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_handlers_set##upbtype(h, f, encode_packed_##lower, &attr); \
9676b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    } else {                                                         \
9677b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_handlers_set##upbtype(h, f, encode_scalar_##lower, &attr); \
9678b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }                                                                \
9679b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    break;
9680b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9681b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    switch (upb_fielddef_descriptortype(f)) {
9682b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      T(DOUBLE,   double,   double);
9683b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      T(FLOAT,    float,    float);
9684b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      T(INT64,    int64,    int64);
9685b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      T(INT32,    int32,    int32);
9686b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      T(FIXED64,  fixed64,  uint64);
9687b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      T(FIXED32,  fixed32,  uint32);
9688b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      T(BOOL,     bool,     bool);
9689b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      T(UINT32,   uint32,   uint32);
9690b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      T(UINT64,   uint64,   uint64);
9691b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      T(ENUM,     enum,     int32);
9692b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      T(SFIXED32, sfixed32, int32);
9693b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      T(SFIXED64, sfixed64, int64);
9694b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      T(SINT32,   sint32,   int32);
9695b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      T(SINT64,   sint64,   int64);
9696b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case UPB_DESCRIPTOR_TYPE_STRING:
9697b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case UPB_DESCRIPTOR_TYPE_BYTES:
9698b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_handlers_setstartstr(h, f, encode_startstr, &attr);
9699b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_handlers_setendstr(h, f, encode_enddelimfield, &attr);
9700b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_handlers_setstring(h, f, encode_strbuf, &attr);
9701b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        break;
9702b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case UPB_DESCRIPTOR_TYPE_MESSAGE:
9703b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_handlers_setstartsubmsg(h, f, encode_startdelimfield, &attr);
9704b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_handlers_setendsubmsg(h, f, encode_enddelimfield, &attr);
9705b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        break;
9706b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case UPB_DESCRIPTOR_TYPE_GROUP: {
9707b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        /* Endgroup takes a different tag (wire_type = END_GROUP). */
9708b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_handlerattr attr2;
9709b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        new_tag(h, f, UPB_WIRE_TYPE_END_GROUP, &attr2);
9710b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9711b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_handlers_setstartsubmsg(h, f, encode_startgroup, &attr);
9712b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_handlers_setendsubmsg(h, f, encode_endgroup, &attr2);
9713b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9714b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_handlerattr_uninit(&attr2);
9715b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        break;
9716b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
9717b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
9718b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9719b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#undef T
9720b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9721b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_handlerattr_uninit(&attr);
9722b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
9723b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
9724b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9725b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_pb_encoder_reset(upb_pb_encoder *e) {
9726b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  e->segptr = NULL;
9727b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  e->top = NULL;
9728b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  e->depth = 0;
9729b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
9730b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9731b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9732b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* public API *****************************************************************/
9733b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9734b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_handlers *upb_pb_encoder_newhandlers(const upb_msgdef *m,
9735b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                               const void *owner) {
9736b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_handlers_newfrozen(m, owner, newhandlers_callback, NULL);
9737b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
9738b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9739b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerupb_pb_encoder *upb_pb_encoder_create(upb_env *env, const upb_handlers *h,
9740b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                      upb_bytessink *output) {
9741b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const size_t initial_bufsize = 256;
9742b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const size_t initial_segbufsize = 16;
9743b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* TODO(haberman): make this configurable. */
9744b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const size_t stack_size = 64;
9745b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#ifndef NDEBUG
9746b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const size_t size_before = upb_env_bytesallocated(env);
9747b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#endif
9748b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9749b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_pb_encoder *e = upb_env_malloc(env, sizeof(upb_pb_encoder));
9750b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!e) return NULL;
9751b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9752b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  e->buf = upb_env_malloc(env, initial_bufsize);
9753b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  e->segbuf = upb_env_malloc(env, initial_segbufsize * sizeof(*e->segbuf));
9754b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  e->stack = upb_env_malloc(env, stack_size * sizeof(*e->stack));
9755b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9756b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!e->buf || !e->segbuf || !e->stack) {
9757b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return NULL;
9758b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
9759b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9760b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  e->limit = e->buf + initial_bufsize;
9761b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  e->seglimit = e->segbuf + initial_segbufsize;
9762b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  e->stacklimit = e->stack + stack_size;
9763b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9764b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_pb_encoder_reset(e);
9765b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_sink_reset(&e->input_, h, e);
9766b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9767b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  e->env = env;
9768b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  e->output_ = output;
9769b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  e->subc = output->closure;
9770b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  e->ptr = e->buf;
9771b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9772b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* If this fails, increase the value in encoder.h. */
9773b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(upb_env_bytesallocated(env) - size_before <= UPB_PB_ENCODER_SIZE);
9774b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return e;
9775b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
9776b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9777b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerupb_sink *upb_pb_encoder_input(upb_pb_encoder *e) { return &e->input_; }
9778b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9779b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9780b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9781b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerupb_filedef **upb_loaddescriptor(const char *buf, size_t n, const void *owner,
9782b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                 upb_status *status) {
9783b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Create handlers. */
9784b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const upb_pbdecodermethod *decoder_m;
9785b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const upb_handlers *reader_h = upb_descreader_newhandlers(&reader_h);
9786b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_env env;
9787b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_pbdecodermethodopts opts;
9788b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_pbdecoder *decoder;
9789b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_descreader *reader;
9790b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bool ok;
9791b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  size_t i;
9792b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_filedef **ret = NULL;
9793b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9794b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_pbdecodermethodopts_init(&opts, reader_h);
9795b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  decoder_m = upb_pbdecodermethod_new(&opts, &decoder_m);
9796b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9797b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_env_init(&env);
9798b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_env_reporterrorsto(&env, status);
9799b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9800b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  reader = upb_descreader_create(&env, reader_h);
9801b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  decoder = upb_pbdecoder_create(&env, decoder_m, upb_descreader_input(reader));
9802b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9803b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Push input data. */
9804b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  ok = upb_bufsrc_putbuf(buf, n, upb_pbdecoder_input(decoder));
9805b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9806b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!ok) {
9807b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    goto cleanup;
9808b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
9809b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9810b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  ret = upb_gmalloc(sizeof (*ret) * (upb_descreader_filecount(reader) + 1));
9811b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9812b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!ret) {
9813b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    goto cleanup;
9814b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
9815b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9816b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for (i = 0; i < upb_descreader_filecount(reader); i++) {
9817b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    ret[i] = upb_descreader_file(reader, i);
9818b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_filedef_ref(ret[i], owner);
9819b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
9820b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9821b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  ret[i] = NULL;
9822b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9823b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammercleanup:
9824b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_env_uninit(&env);
9825b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_handlers_unref(reader_h, &reader_h);
9826b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_pbdecodermethod_unref(decoder_m, &decoder_m);
9827b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return ret;
9828b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
9829b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/*
9830b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * upb::pb::TextPrinter
9831b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *
9832b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * OPT: This is not optimized at all.  It uses printf() which parses the format
9833b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * string every time, and it allocates memory for every put.
9834b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer */
9835b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9836b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9837b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <ctype.h>
9838b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <float.h>
9839b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <inttypes.h>
9840b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <stdarg.h>
9841b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <stdio.h>
9842b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <string.h>
9843b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9844b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9845b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstruct upb_textprinter {
9846b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_sink input_;
9847b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_bytessink *output_;
9848b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  int indent_depth_;
9849b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bool single_line_;
9850b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  void *subc;
9851b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer};
9852b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9853b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#define CHECK(x) if ((x) < 0) goto err;
9854b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9855b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic const char *shortname(const char *longname) {
9856b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const char *last = strrchr(longname, '.');
9857b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return last ? last + 1 : longname;
9858b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
9859b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9860b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic int indent(upb_textprinter *p) {
9861b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  int i;
9862b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!p->single_line_)
9863b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    for (i = 0; i < p->indent_depth_; i++)
9864b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_bytessink_putbuf(p->output_, p->subc, "  ", 2, NULL);
9865b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return 0;
9866b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
9867b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9868b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic int endfield(upb_textprinter *p) {
9869b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const char ch = (p->single_line_ ? ' ' : '\n');
9870b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_bytessink_putbuf(p->output_, p->subc, &ch, 1, NULL);
9871b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return 0;
9872b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
9873b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9874b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic int putescaped(upb_textprinter *p, const char *buf, size_t len,
9875b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                      bool preserve_utf8) {
9876b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Based on CEscapeInternal() from Google's protobuf release. */
9877b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  char dstbuf[4096], *dst = dstbuf, *dstend = dstbuf + sizeof(dstbuf);
9878b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const char *end = buf + len;
9879b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9880b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* I think hex is prettier and more useful, but proto2 uses octal; should
9881b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * investigate whether it can parse hex also. */
9882b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const bool use_hex = false;
9883b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bool last_hex_escape = false; /* true if last output char was \xNN */
9884b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9885b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for (; buf < end; buf++) {
9886b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    bool is_hex_escape;
9887b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9888b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (dstend - dst < 4) {
9889b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_bytessink_putbuf(p->output_, p->subc, dstbuf, dst - dstbuf, NULL);
9890b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      dst = dstbuf;
9891b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
9892b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9893b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    is_hex_escape = false;
9894b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    switch (*buf) {
9895b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case '\n': *(dst++) = '\\'; *(dst++) = 'n';  break;
9896b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case '\r': *(dst++) = '\\'; *(dst++) = 'r';  break;
9897b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case '\t': *(dst++) = '\\'; *(dst++) = 't';  break;
9898b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case '\"': *(dst++) = '\\'; *(dst++) = '\"'; break;
9899b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case '\'': *(dst++) = '\\'; *(dst++) = '\''; break;
9900b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case '\\': *(dst++) = '\\'; *(dst++) = '\\'; break;
9901b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      default:
9902b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        /* Note that if we emit \xNN and the buf character after that is a hex
9903b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer         * digit then that digit must be escaped too to prevent it being
9904b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer         * interpreted as part of the character code by C. */
9905b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        if ((!preserve_utf8 || (uint8_t)*buf < 0x80) &&
9906b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer            (!isprint(*buf) || (last_hex_escape && isxdigit(*buf)))) {
9907b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          sprintf(dst, (use_hex ? "\\x%02x" : "\\%03o"), (uint8_t)*buf);
9908b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          is_hex_escape = use_hex;
9909b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          dst += 4;
9910b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        } else {
9911b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          *(dst++) = *buf; break;
9912b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        }
9913b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
9914b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    last_hex_escape = is_hex_escape;
9915b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
9916b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Flush remaining data. */
9917b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_bytessink_putbuf(p->output_, p->subc, dstbuf, dst - dstbuf, NULL);
9918b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return 0;
9919b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
9920b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9921b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool putf(upb_textprinter *p, const char *fmt, ...) {
9922b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  va_list args;
9923b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  va_list args_copy;
9924b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  char *str;
9925b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  int written;
9926b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  int len;
9927b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bool ok;
9928b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9929b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  va_start(args, fmt);
9930b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9931b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Run once to get the length of the string. */
9932b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  _upb_va_copy(args_copy, args);
9933b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  len = _upb_vsnprintf(NULL, 0, fmt, args_copy);
9934b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  va_end(args_copy);
9935b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9936b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* + 1 for NULL terminator (vsprintf() requires it even if we don't). */
9937b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  str = upb_gmalloc(len + 1);
9938b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!str) return false;
9939b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  written = vsprintf(str, fmt, args);
9940b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  va_end(args);
9941b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_ASSERT_VAR(written, written == len);
9942b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9943b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  ok = upb_bytessink_putbuf(p->output_, p->subc, str, len, NULL);
9944b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_gfree(str);
9945b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return ok;
9946b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
9947b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9948b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9949b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* handlers *******************************************************************/
9950b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9951b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool textprinter_startmsg(void *c, const void *hd) {
9952b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_textprinter *p = c;
9953b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(hd);
9954b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (p->indent_depth_ == 0) {
9955b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_bytessink_start(p->output_, 0, &p->subc);
9956b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
9957b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
9958b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
9959b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9960b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool textprinter_endmsg(void *c, const void *hd, upb_status *s) {
9961b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_textprinter *p = c;
9962b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(hd);
9963b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(s);
9964b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (p->indent_depth_ == 0) {
9965b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_bytessink_end(p->output_);
9966b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
9967b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
9968b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
9969b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9970b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#define TYPE(name, ctype, fmt) \
9971b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  static bool textprinter_put ## name(void *closure, const void *handler_data, \
9972b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                      ctype val) {                             \
9973b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_textprinter *p = closure;                                              \
9974b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    const upb_fielddef *f = handler_data;                                      \
9975b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    CHECK(indent(p));                                                          \
9976b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putf(p, "%s: " fmt, upb_fielddef_name(f), val);                            \
9977b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    CHECK(endfield(p));                                                        \
9978b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return true;                                                               \
9979b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  err:                                                                         \
9980b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;                                                              \
9981b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
9982b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9983b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool textprinter_putbool(void *closure, const void *handler_data,
9984b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                bool val) {
9985b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_textprinter *p = closure;
9986b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const upb_fielddef *f = handler_data;
9987b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  CHECK(indent(p));
9988b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  putf(p, "%s: %s", upb_fielddef_name(f), val ? "true" : "false");
9989b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  CHECK(endfield(p));
9990b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
9991b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammererr:
9992b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return false;
9993b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
9994b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9995b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#define STRINGIFY_HELPER(x) #x
9996b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#define STRINGIFY_MACROVAL(x) STRINGIFY_HELPER(x)
9997b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
9998b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerTYPE(int32,  int32_t,  "%" PRId32)
9999b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerTYPE(int64,  int64_t,  "%" PRId64)
10000b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerTYPE(uint32, uint32_t, "%" PRIu32)
10001b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerTYPE(uint64, uint64_t, "%" PRIu64)
10002b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerTYPE(float,  float,    "%." STRINGIFY_MACROVAL(FLT_DIG) "g")
10003b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerTYPE(double, double,   "%." STRINGIFY_MACROVAL(DBL_DIG) "g")
10004b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10005b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#undef TYPE
10006b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10007b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Output a symbolic value from the enum if found, else just print as int32. */
10008b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool textprinter_putenum(void *closure, const void *handler_data,
10009b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                int32_t val) {
10010b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_textprinter *p = closure;
10011b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const upb_fielddef *f = handler_data;
10012b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const upb_enumdef *enum_def = upb_downcast_enumdef(upb_fielddef_subdef(f));
10013b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const char *label = upb_enumdef_iton(enum_def, val);
10014b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (label) {
10015b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    indent(p);
10016b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putf(p, "%s: %s", upb_fielddef_name(f), label);
10017b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    endfield(p);
10018b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
10019b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (!textprinter_putint32(closure, handler_data, val))
10020b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return false;
10021b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
10022b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
10023b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
10024b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10025b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void *textprinter_startstr(void *closure, const void *handler_data,
10026b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                      size_t size_hint) {
10027b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_textprinter *p = closure;
10028b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const upb_fielddef *f = handler_data;
10029b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(size_hint);
10030b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  indent(p);
10031b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  putf(p, "%s: \"", upb_fielddef_name(f));
10032b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return p;
10033b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
10034b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10035b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool textprinter_endstr(void *closure, const void *handler_data) {
10036b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_textprinter *p = closure;
10037b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(handler_data);
10038b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  putf(p, "\"");
10039b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  endfield(p);
10040b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
10041b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
10042b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10043b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic size_t textprinter_putstr(void *closure, const void *hd, const char *buf,
10044b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                 size_t len, const upb_bufhandle *handle) {
10045b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_textprinter *p = closure;
10046b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const upb_fielddef *f = hd;
10047b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(handle);
10048b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  CHECK(putescaped(p, buf, len, upb_fielddef_type(f) == UPB_TYPE_STRING));
10049b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return len;
10050b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammererr:
10051b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return 0;
10052b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
10053b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10054b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void *textprinter_startsubmsg(void *closure, const void *handler_data) {
10055b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_textprinter *p = closure;
10056b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const char *name = handler_data;
10057b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  CHECK(indent(p));
10058b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  putf(p, "%s {%c", name, p->single_line_ ? ' ' : '\n');
10059b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  p->indent_depth_++;
10060b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return p;
10061b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammererr:
10062b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return UPB_BREAK;
10063b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
10064b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10065b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool textprinter_endsubmsg(void *closure, const void *handler_data) {
10066b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_textprinter *p = closure;
10067b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(handler_data);
10068b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  p->indent_depth_--;
10069b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  CHECK(indent(p));
10070b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_bytessink_putbuf(p->output_, p->subc, "}", 1, NULL);
10071b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  CHECK(endfield(p));
10072b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
10073b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammererr:
10074b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return false;
10075b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
10076b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10077b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void onmreg(const void *c, upb_handlers *h) {
10078b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const upb_msgdef *m = upb_handlers_msgdef(h);
10079b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_msg_field_iter i;
10080b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(c);
10081b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10082b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_handlers_setstartmsg(h, textprinter_startmsg, NULL);
10083b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_handlers_setendmsg(h, textprinter_endmsg, NULL);
10084b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10085b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for(upb_msg_field_begin(&i, m);
10086b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      !upb_msg_field_done(&i);
10087b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_msg_field_next(&i)) {
10088b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_fielddef *f = upb_msg_iter_field(&i);
10089b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
10090b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_handlerattr_sethandlerdata(&attr, f);
10091b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    switch (upb_fielddef_type(f)) {
10092b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case UPB_TYPE_INT32:
10093b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_handlers_setint32(h, f, textprinter_putint32, &attr);
10094b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        break;
10095b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case UPB_TYPE_INT64:
10096b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_handlers_setint64(h, f, textprinter_putint64, &attr);
10097b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        break;
10098b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case UPB_TYPE_UINT32:
10099b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_handlers_setuint32(h, f, textprinter_putuint32, &attr);
10100b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        break;
10101b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case UPB_TYPE_UINT64:
10102b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_handlers_setuint64(h, f, textprinter_putuint64, &attr);
10103b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        break;
10104b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case UPB_TYPE_FLOAT:
10105b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_handlers_setfloat(h, f, textprinter_putfloat, &attr);
10106b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        break;
10107b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case UPB_TYPE_DOUBLE:
10108b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_handlers_setdouble(h, f, textprinter_putdouble, &attr);
10109b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        break;
10110b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case UPB_TYPE_BOOL:
10111b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_handlers_setbool(h, f, textprinter_putbool, &attr);
10112b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        break;
10113b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case UPB_TYPE_STRING:
10114b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case UPB_TYPE_BYTES:
10115b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_handlers_setstartstr(h, f, textprinter_startstr, &attr);
10116b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_handlers_setstring(h, f, textprinter_putstr, &attr);
10117b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_handlers_setendstr(h, f, textprinter_endstr, &attr);
10118b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        break;
10119b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case UPB_TYPE_MESSAGE: {
10120b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        const char *name =
10121b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer            upb_fielddef_istagdelim(f)
10122b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                ? shortname(upb_msgdef_fullname(upb_fielddef_msgsubdef(f)))
10123b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                : upb_fielddef_name(f);
10124b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_handlerattr_sethandlerdata(&attr, name);
10125b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_handlers_setstartsubmsg(h, f, textprinter_startsubmsg, &attr);
10126b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_handlers_setendsubmsg(h, f, textprinter_endsubmsg, &attr);
10127b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        break;
10128b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
10129b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case UPB_TYPE_ENUM:
10130b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_handlers_setint32(h, f, textprinter_putenum, &attr);
10131b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        break;
10132b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
10133b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
10134b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
10135b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10136b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void textprinter_reset(upb_textprinter *p, bool single_line) {
10137b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  p->single_line_ = single_line;
10138b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  p->indent_depth_ = 0;
10139b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
10140b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10141b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10142b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Public API *****************************************************************/
10143b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10144b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerupb_textprinter *upb_textprinter_create(upb_env *env, const upb_handlers *h,
10145b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                        upb_bytessink *output) {
10146b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_textprinter *p = upb_env_malloc(env, sizeof(upb_textprinter));
10147b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!p) return NULL;
10148b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10149b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  p->output_ = output;
10150b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_sink_reset(&p->input_, h, p);
10151b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  textprinter_reset(p, false);
10152b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10153b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return p;
10154b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
10155b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10156b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_handlers *upb_textprinter_newhandlers(const upb_msgdef *m,
10157b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                                const void *owner) {
10158b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_handlers_newfrozen(m, owner, &onmreg, NULL);
10159b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
10160b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10161b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerupb_sink *upb_textprinter_input(upb_textprinter *p) { return &p->input_; }
10162b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10163b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid upb_textprinter_setsingleline(upb_textprinter *p, bool single_line) {
10164b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  p->single_line_ = single_line;
10165b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
10166b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10167b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10168b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Index is descriptor type. */
10169b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst uint8_t upb_pb_native_wire_types[] = {
10170b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_WIRE_TYPE_END_GROUP,     /* ENDGROUP */
10171b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_WIRE_TYPE_64BIT,         /* DOUBLE */
10172b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_WIRE_TYPE_32BIT,         /* FLOAT */
10173b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_WIRE_TYPE_VARINT,        /* INT64 */
10174b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_WIRE_TYPE_VARINT,        /* UINT64 */
10175b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_WIRE_TYPE_VARINT,        /* INT32 */
10176b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_WIRE_TYPE_64BIT,         /* FIXED64 */
10177b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_WIRE_TYPE_32BIT,         /* FIXED32 */
10178b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_WIRE_TYPE_VARINT,        /* BOOL */
10179b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_WIRE_TYPE_DELIMITED,     /* STRING */
10180b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_WIRE_TYPE_START_GROUP,   /* GROUP */
10181b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_WIRE_TYPE_DELIMITED,     /* MESSAGE */
10182b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_WIRE_TYPE_DELIMITED,     /* BYTES */
10183b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_WIRE_TYPE_VARINT,        /* UINT32 */
10184b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_WIRE_TYPE_VARINT,        /* ENUM */
10185b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_WIRE_TYPE_32BIT,         /* SFIXED32 */
10186b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_WIRE_TYPE_64BIT,         /* SFIXED64 */
10187b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_WIRE_TYPE_VARINT,        /* SINT32 */
10188b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_WIRE_TYPE_VARINT,        /* SINT64 */
10189b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer};
10190b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10191b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* A basic branch-based decoder, uses 32-bit values to get good performance
10192b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * on 32-bit architectures (but performs well on 64-bits also).
10193b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * This scheme comes from the original Google Protobuf implementation
10194b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * (proto2). */
10195b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerupb_decoderet upb_vdecode_max8_branch32(upb_decoderet r) {
10196b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_decoderet err = {NULL, 0};
10197b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const char *p = r.p;
10198b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  uint32_t low = (uint32_t)r.val;
10199b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  uint32_t high = 0;
10200b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  uint32_t b;
10201b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  b = *(p++); low  |= (b & 0x7fU) << 14; if (!(b & 0x80)) goto done;
10202b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  b = *(p++); low  |= (b & 0x7fU) << 21; if (!(b & 0x80)) goto done;
10203b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  b = *(p++); low  |= (b & 0x7fU) << 28;
10204b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer              high  = (b & 0x7fU) >>  4; if (!(b & 0x80)) goto done;
10205b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  b = *(p++); high |= (b & 0x7fU) <<  3; if (!(b & 0x80)) goto done;
10206b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  b = *(p++); high |= (b & 0x7fU) << 10; if (!(b & 0x80)) goto done;
10207b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  b = *(p++); high |= (b & 0x7fU) << 17; if (!(b & 0x80)) goto done;
10208b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  b = *(p++); high |= (b & 0x7fU) << 24; if (!(b & 0x80)) goto done;
10209b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  b = *(p++); high |= (b & 0x7fU) << 31; if (!(b & 0x80)) goto done;
10210b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return err;
10211b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10212b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerdone:
10213b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  r.val = ((uint64_t)high << 32) | low;
10214b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  r.p = p;
10215b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return r;
10216b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
10217b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10218b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Like the previous, but uses 64-bit values. */
10219b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerupb_decoderet upb_vdecode_max8_branch64(upb_decoderet r) {
10220b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const char *p = r.p;
10221b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  uint64_t val = r.val;
10222b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  uint64_t b;
10223b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_decoderet err = {NULL, 0};
10224b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  b = *(p++); val |= (b & 0x7fU) << 14; if (!(b & 0x80)) goto done;
10225b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  b = *(p++); val |= (b & 0x7fU) << 21; if (!(b & 0x80)) goto done;
10226b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  b = *(p++); val |= (b & 0x7fU) << 28; if (!(b & 0x80)) goto done;
10227b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  b = *(p++); val |= (b & 0x7fU) << 35; if (!(b & 0x80)) goto done;
10228b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  b = *(p++); val |= (b & 0x7fU) << 42; if (!(b & 0x80)) goto done;
10229b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  b = *(p++); val |= (b & 0x7fU) << 49; if (!(b & 0x80)) goto done;
10230b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  b = *(p++); val |= (b & 0x7fU) << 56; if (!(b & 0x80)) goto done;
10231b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  b = *(p++); val |= (b & 0x7fU) << 63; if (!(b & 0x80)) goto done;
10232b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return err;
10233b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10234b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerdone:
10235b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  r.val = val;
10236b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  r.p = p;
10237b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return r;
10238b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
10239b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10240b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Given an encoded varint v, returns an integer with a single bit set that
10241b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * indicates the end of the varint.  Subtracting one from this value will
10242b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * yield a mask that leaves only bits that are part of the varint.  Returns
10243b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * 0 if the varint is unterminated. */
10244b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic uint64_t upb_get_vstopbit(uint64_t v) {
10245b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  uint64_t cbits = v | 0x7f7f7f7f7f7f7f7fULL;
10246b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return ~cbits & (cbits+1);
10247b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
10248b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10249b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* A branchless decoder.  Credit to Pascal Massimino for the bit-twiddling. */
10250b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerupb_decoderet upb_vdecode_max8_massimino(upb_decoderet r) {
10251b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  uint64_t b;
10252b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  uint64_t stop_bit;
10253b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_decoderet my_r;
10254b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  memcpy(&b, r.p, sizeof(b));
10255b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  stop_bit = upb_get_vstopbit(b);
10256b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  b =  (b & 0x7f7f7f7f7f7f7f7fULL) & (stop_bit - 1);
10257b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  b +=       b & 0x007f007f007f007fULL;
10258b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  b +=  3 * (b & 0x0000ffff0000ffffULL);
10259b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  b += 15 * (b & 0x00000000ffffffffULL);
10260b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (stop_bit == 0) {
10261b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Error: unterminated varint. */
10262b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_decoderet err_r = {(void*)0, 0};
10263b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return err_r;
10264b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
10265b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  my_r = upb_decoderet_make(r.p + ((__builtin_ctzll(stop_bit) + 1) / 8),
10266b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                            r.val | (b << 7));
10267b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return my_r;
10268b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
10269b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10270b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* A branchless decoder.  Credit to Daniel Wright for the bit-twiddling. */
10271b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerupb_decoderet upb_vdecode_max8_wright(upb_decoderet r) {
10272b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  uint64_t b;
10273b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  uint64_t stop_bit;
10274b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_decoderet my_r;
10275b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  memcpy(&b, r.p, sizeof(b));
10276b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  stop_bit = upb_get_vstopbit(b);
10277b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  b &= (stop_bit - 1);
10278b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  b = ((b & 0x7f007f007f007f00ULL) >> 1) | (b & 0x007f007f007f007fULL);
10279b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  b = ((b & 0xffff0000ffff0000ULL) >> 2) | (b & 0x0000ffff0000ffffULL);
10280b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  b = ((b & 0xffffffff00000000ULL) >> 4) | (b & 0x00000000ffffffffULL);
10281b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (stop_bit == 0) {
10282b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Error: unterminated varint. */
10283b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_decoderet err_r = {(void*)0, 0};
10284b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return err_r;
10285b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
10286b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  my_r = upb_decoderet_make(r.p + ((__builtin_ctzll(stop_bit) + 1) / 8),
10287b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                            r.val | (b << 14));
10288b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return my_r;
10289b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
10290b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10291b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#line 1 "upb/json/parser.rl"
10292b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/*
10293b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** upb::json::Parser (upb_json_parser)
10294b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer**
10295b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** A parser that uses the Ragel State Machine Compiler to generate
10296b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** the finite automata.
10297b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer**
10298b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** Ragel only natively handles regular languages, but we can manually
10299b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** program it a bit to handle context-free languages like JSON, by using
10300b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** the "fcall" and "fret" constructs.
10301b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer**
10302b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** This parser can handle the basics, but needs several things to be fleshed
10303b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** out:
10304b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer**
10305b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** - handling of unicode escape sequences (including high surrogate pairs).
10306b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** - properly check and report errors for unknown fields, stack overflow,
10307b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer**   improper array nesting (or lack of nesting).
10308b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** - handling of base64 sequences with padding characters.
10309b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** - handling of push-back (non-success returns from sink functions).
10310b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** - handling of keys/escape-sequences/etc that span input buffers.
10311b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer*/
10312b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10313b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <assert.h>
10314b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <errno.h>
10315b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <stdint.h>
10316b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <stdlib.h>
10317b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <string.h>
10318b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10319b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10320b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#define UPB_JSON_MAX_DEPTH 64
10321b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10322b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammertypedef struct {
10323b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_sink sink;
10324b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10325b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* The current message in which we're parsing, and the field whose value we're
10326b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * expecting next. */
10327b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const upb_msgdef *m;
10328b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const upb_fielddef *f;
10329b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10330b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* The table mapping json name to fielddef for this message. */
10331b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_strtable *name_table;
10332b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10333b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* We are in a repeated-field context, ready to emit mapentries as
10334b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * submessages. This flag alters the start-of-object (open-brace) behavior to
10335b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * begin a sequence of mapentry messages rather than a single submessage. */
10336b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bool is_map;
10337b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10338b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* We are in a map-entry message context. This flag is set when parsing the
10339b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * value field of a single map entry and indicates to all value-field parsers
10340b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * (subobjects, strings, numbers, and bools) that the map-entry submessage
10341b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * should end as soon as the value is parsed. */
10342b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bool is_mapentry;
10343b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10344b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* If |is_map| or |is_mapentry| is true, |mapfield| refers to the parent
10345b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * message's map field that we're currently parsing. This differs from |f|
10346b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * because |f| is the field in the *current* message (i.e., the map-entry
10347b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * message itself), not the parent's field that leads to this map. */
10348b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const upb_fielddef *mapfield;
10349b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer} upb_jsonparser_frame;
10350b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10351b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstruct upb_json_parser {
10352b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_env *env;
10353b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const upb_json_parsermethod *method;
10354b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_bytessink input_;
10355b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10356b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Stack to track the JSON scopes we are in. */
10357b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_jsonparser_frame stack[UPB_JSON_MAX_DEPTH];
10358b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_jsonparser_frame *top;
10359b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_jsonparser_frame *limit;
10360b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10361b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_status status;
10362b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10363b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Ragel's internal parsing stack for the parsing state machine. */
10364b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  int current_state;
10365b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  int parser_stack[UPB_JSON_MAX_DEPTH];
10366b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  int parser_top;
10367b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10368b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* The handle for the current buffer. */
10369b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const upb_bufhandle *handle;
10370b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10371b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Accumulate buffer.  See details in parser.rl. */
10372b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const char *accumulated;
10373b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  size_t accumulated_len;
10374b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  char *accumulate_buf;
10375b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  size_t accumulate_buf_size;
10376b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10377b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Multi-part text data.  See details in parser.rl. */
10378b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  int multipart_state;
10379b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_selector_t string_selector;
10380b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10381b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Input capture.  See details in parser.rl. */
10382b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const char *capture;
10383b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10384b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Intermediate result of parsing a unicode escape sequence. */
10385b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  uint32_t digit;
10386b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer};
10387b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10388b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstruct upb_json_parsermethod {
10389b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_refcounted base;
10390b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10391b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_byteshandler input_handler_;
10392b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10393b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Mainly for the purposes of refcounting, so all the fielddefs we point
10394b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * to stay alive. */
10395b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const upb_msgdef *msg;
10396b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10397b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Keys are upb_msgdef*, values are upb_strtable (json_name -> fielddef) */
10398b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable name_tables;
10399b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer};
10400b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10401b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#define PARSER_CHECK_RETURN(x) if (!(x)) return false
10402b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10403b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Used to signal that a capture has been suspended. */
10404b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic char suspend_capture;
10405b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10406b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic upb_selector_t getsel_for_handlertype(upb_json_parser *p,
10407b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                             upb_handlertype_t type) {
10408b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_selector_t sel;
10409b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bool ok = upb_handlers_getselector(p->top->f, type, &sel);
10410b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_ASSERT_VAR(ok, ok);
10411b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return sel;
10412b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
10413b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10414b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic upb_selector_t parser_getsel(upb_json_parser *p) {
10415b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return getsel_for_handlertype(
10416b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      p, upb_handlers_getprimitivehandlertype(p->top->f));
10417b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
10418b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10419b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool check_stack(upb_json_parser *p) {
10420b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if ((p->top + 1) == p->limit) {
10421b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_status_seterrmsg(&p->status, "Nesting too deep");
10422b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_env_reporterror(p->env, &p->status);
10423b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
10424b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
10425b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10426b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
10427b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
10428b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10429b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void set_name_table(upb_json_parser *p, upb_jsonparser_frame *frame) {
10430b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_value v;
10431b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bool ok = upb_inttable_lookupptr(&p->method->name_tables, frame->m, &v);
10432b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_ASSERT_VAR(ok, ok);
10433b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  frame->name_table = upb_value_getptr(v);
10434b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
10435b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10436b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* There are GCC/Clang built-ins for overflow checking which we could start
10437b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * using if there was any performance benefit to it. */
10438b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10439b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool checked_add(size_t a, size_t b, size_t *c) {
10440b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (SIZE_MAX - a < b) return false;
10441b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  *c = a + b;
10442b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
10443b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
10444b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10445b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic size_t saturating_multiply(size_t a, size_t b) {
10446b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* size_t is unsigned, so this is defined behavior even on overflow. */
10447b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  size_t ret = a * b;
10448b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (b != 0 && ret / b != a) {
10449b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    ret = SIZE_MAX;
10450b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
10451b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return ret;
10452b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
10453b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10454b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10455b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Base64 decoding ************************************************************/
10456b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10457b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* TODO(haberman): make this streaming. */
10458b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10459b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic const signed char b64table[] = {
10460b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
10461b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
10462b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
10463b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
10464b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
10465b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  -1,      -1,      -1,      62/*+*/, -1,      -1,      -1,      63/*/ */,
10466b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  52/*0*/, 53/*1*/, 54/*2*/, 55/*3*/, 56/*4*/, 57/*5*/, 58/*6*/, 59/*7*/,
10467b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  60/*8*/, 61/*9*/, -1,      -1,      -1,      -1,      -1,      -1,
10468b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  -1,       0/*A*/,  1/*B*/,  2/*C*/,  3/*D*/,  4/*E*/,  5/*F*/,  6/*G*/,
10469b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  07/*H*/,  8/*I*/,  9/*J*/, 10/*K*/, 11/*L*/, 12/*M*/, 13/*N*/, 14/*O*/,
10470b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  15/*P*/, 16/*Q*/, 17/*R*/, 18/*S*/, 19/*T*/, 20/*U*/, 21/*V*/, 22/*W*/,
10471b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  23/*X*/, 24/*Y*/, 25/*Z*/, -1,      -1,      -1,      -1,      -1,
10472b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  -1,      26/*a*/, 27/*b*/, 28/*c*/, 29/*d*/, 30/*e*/, 31/*f*/, 32/*g*/,
10473b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  33/*h*/, 34/*i*/, 35/*j*/, 36/*k*/, 37/*l*/, 38/*m*/, 39/*n*/, 40/*o*/,
10474b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  41/*p*/, 42/*q*/, 43/*r*/, 44/*s*/, 45/*t*/, 46/*u*/, 47/*v*/, 48/*w*/,
10475b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  49/*x*/, 50/*y*/, 51/*z*/, -1,      -1,      -1,      -1,      -1,
10476b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
10477b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
10478b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
10479b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
10480b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
10481b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
10482b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
10483b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
10484b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
10485b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
10486b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
10487b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
10488b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
10489b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
10490b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
10491b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1
10492b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer};
10493b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10494b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Returns the table value sign-extended to 32 bits.  Knowing that the upper
10495b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * bits will be 1 for unrecognized characters makes it easier to check for
10496b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * this error condition later (see below). */
10497b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerint32_t b64lookup(unsigned char ch) { return b64table[ch]; }
10498b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10499b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Returns true if the given character is not a valid base64 character or
10500b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * padding. */
10501b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool nonbase64(unsigned char ch) { return b64lookup(ch) == -1 && ch != '='; }
10502b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10503b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool base64_push(upb_json_parser *p, upb_selector_t sel, const char *ptr,
10504b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                        size_t len) {
10505b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const char *limit = ptr + len;
10506b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for (; ptr < limit; ptr += 4) {
10507b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    uint32_t val;
10508b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    char output[3];
10509b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10510b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (limit - ptr < 4) {
10511b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_status_seterrf(&p->status,
10512b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                         "Base64 input for bytes field not a multiple of 4: %s",
10513b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                         upb_fielddef_name(p->top->f));
10514b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_env_reporterror(p->env, &p->status);
10515b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return false;
10516b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
10517b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10518b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    val = b64lookup(ptr[0]) << 18 |
10519b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          b64lookup(ptr[1]) << 12 |
10520b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          b64lookup(ptr[2]) << 6  |
10521b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          b64lookup(ptr[3]);
10522b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10523b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Test the upper bit; returns true if any of the characters returned -1. */
10524b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (val & 0x80000000) {
10525b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      goto otherchar;
10526b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
10527b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10528b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    output[0] = val >> 16;
10529b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    output[1] = (val >> 8) & 0xff;
10530b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    output[2] = val & 0xff;
10531b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_sink_putstring(&p->top->sink, sel, output, 3, NULL);
10532b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
10533b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
10534b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10535b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerotherchar:
10536b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (nonbase64(ptr[0]) || nonbase64(ptr[1]) || nonbase64(ptr[2]) ||
10537b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      nonbase64(ptr[3]) ) {
10538b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_status_seterrf(&p->status,
10539b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                       "Non-base64 characters in bytes field: %s",
10540b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                       upb_fielddef_name(p->top->f));
10541b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_env_reporterror(p->env, &p->status);
10542b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
10543b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } if (ptr[2] == '=') {
10544b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    uint32_t val;
10545b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    char output;
10546b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10547b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Last group contains only two input bytes, one output byte. */
10548b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (ptr[0] == '=' || ptr[1] == '=' || ptr[3] != '=') {
10549b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      goto badpadding;
10550b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
10551b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10552b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    val = b64lookup(ptr[0]) << 18 |
10553b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          b64lookup(ptr[1]) << 12;
10554b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10555b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    assert(!(val & 0x80000000));
10556b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    output = val >> 16;
10557b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_sink_putstring(&p->top->sink, sel, &output, 1, NULL);
10558b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return true;
10559b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
10560b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    uint32_t val;
10561b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    char output[2];
10562b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10563b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Last group contains only three input bytes, two output bytes. */
10564b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (ptr[0] == '=' || ptr[1] == '=' || ptr[2] == '=') {
10565b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      goto badpadding;
10566b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
10567b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10568b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    val = b64lookup(ptr[0]) << 18 |
10569b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          b64lookup(ptr[1]) << 12 |
10570b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          b64lookup(ptr[2]) << 6;
10571b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10572b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    output[0] = val >> 16;
10573b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    output[1] = (val >> 8) & 0xff;
10574b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_sink_putstring(&p->top->sink, sel, output, 2, NULL);
10575b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return true;
10576b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
10577b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10578b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbadpadding:
10579b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_status_seterrf(&p->status,
10580b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                     "Incorrect base64 padding for field: %s (%.*s)",
10581b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                     upb_fielddef_name(p->top->f),
10582b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                     4, ptr);
10583b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_env_reporterror(p->env, &p->status);
10584b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return false;
10585b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
10586b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10587b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10588b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Accumulate buffer **********************************************************/
10589b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10590b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Functionality for accumulating a buffer.
10591b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *
10592b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Some parts of the parser need an entire value as a contiguous string.  For
10593b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * example, to look up a member name in a hash table, or to turn a string into
10594b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * a number, the relevant library routines need the input string to be in
10595b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * contiguous memory, even if the value spanned two or more buffers in the
10596b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * input.  These routines handle that.
10597b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *
10598b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * In the common case we can just point to the input buffer to get this
10599b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * contiguous string and avoid any actual copy.  So we optimistically begin
10600b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * this way.  But there are a few cases where we must instead copy into a
10601b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * separate buffer:
10602b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *
10603b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *   1. The string was not contiguous in the input (it spanned buffers).
10604b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *
10605b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *   2. The string included escape sequences that need to be interpreted to get
10606b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *      the true value in a contiguous buffer. */
10607b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10608b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void assert_accumulate_empty(upb_json_parser *p) {
10609b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(p);
10610b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(p->accumulated == NULL);
10611b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(p->accumulated_len == 0);
10612b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
10613b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10614b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void accumulate_clear(upb_json_parser *p) {
10615b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  p->accumulated = NULL;
10616b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  p->accumulated_len = 0;
10617b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
10618b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10619b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Used internally by accumulate_append(). */
10620b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool accumulate_realloc(upb_json_parser *p, size_t need) {
10621b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  void *mem;
10622b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  size_t old_size = p->accumulate_buf_size;
10623b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  size_t new_size = UPB_MAX(old_size, 128);
10624b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  while (new_size < need) {
10625b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    new_size = saturating_multiply(new_size, 2);
10626b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
10627b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10628b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  mem = upb_env_realloc(p->env, p->accumulate_buf, old_size, new_size);
10629b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!mem) {
10630b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_status_seterrmsg(&p->status, "Out of memory allocating buffer.");
10631b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_env_reporterror(p->env, &p->status);
10632b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
10633b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
10634b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10635b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  p->accumulate_buf = mem;
10636b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  p->accumulate_buf_size = new_size;
10637b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
10638b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
10639b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10640b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Logically appends the given data to the append buffer.
10641b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * If "can_alias" is true, we will try to avoid actually copying, but the buffer
10642b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * must be valid until the next accumulate_append() call (if any). */
10643b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool accumulate_append(upb_json_parser *p, const char *buf, size_t len,
10644b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                              bool can_alias) {
10645b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  size_t need;
10646b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10647b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!p->accumulated && can_alias) {
10648b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    p->accumulated = buf;
10649b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    p->accumulated_len = len;
10650b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return true;
10651b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
10652b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10653b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!checked_add(p->accumulated_len, len, &need)) {
10654b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_status_seterrmsg(&p->status, "Integer overflow.");
10655b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_env_reporterror(p->env, &p->status);
10656b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
10657b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
10658b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10659b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (need > p->accumulate_buf_size && !accumulate_realloc(p, need)) {
10660b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
10661b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
10662b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10663b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (p->accumulated != p->accumulate_buf) {
10664b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    memcpy(p->accumulate_buf, p->accumulated, p->accumulated_len);
10665b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    p->accumulated = p->accumulate_buf;
10666b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
10667b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10668b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  memcpy(p->accumulate_buf + p->accumulated_len, buf, len);
10669b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  p->accumulated_len += len;
10670b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
10671b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
10672b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10673b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Returns a pointer to the data accumulated since the last accumulate_clear()
10674b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * call, and writes the length to *len.  This with point either to the input
10675b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * buffer or a temporary accumulate buffer. */
10676b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic const char *accumulate_getptr(upb_json_parser *p, size_t *len) {
10677b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(p->accumulated);
10678b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  *len = p->accumulated_len;
10679b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return p->accumulated;
10680b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
10681b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10682b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10683b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Mult-part text data ********************************************************/
10684b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10685b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* When we have text data in the input, it can often come in multiple segments.
10686b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * For example, there may be some raw string data followed by an escape
10687b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * sequence.  The two segments are processed with different logic.  Also buffer
10688b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * seams in the input can cause multiple segments.
10689b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *
10690b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * As we see segments, there are two main cases for how we want to process them:
10691b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *
10692b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *  1. we want to push the captured input directly to string handlers.
10693b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *
10694b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *  2. we need to accumulate all the parts into a contiguous buffer for further
10695b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *     processing (field name lookup, string->number conversion, etc). */
10696b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10697b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* This is the set of states for p->multipart_state. */
10698b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerenum {
10699b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* We are not currently processing multipart data. */
10700b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  MULTIPART_INACTIVE = 0,
10701b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10702b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* We are processing multipart data by accumulating it into a contiguous
10703b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * buffer. */
10704b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  MULTIPART_ACCUMULATE = 1,
10705b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10706b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* We are processing multipart data by pushing each part directly to the
10707b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * current string handlers. */
10708b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  MULTIPART_PUSHEAGERLY = 2
10709b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer};
10710b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10711b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Start a multi-part text value where we accumulate the data for processing at
10712b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * the end. */
10713b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void multipart_startaccum(upb_json_parser *p) {
10714b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert_accumulate_empty(p);
10715b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(p->multipart_state == MULTIPART_INACTIVE);
10716b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  p->multipart_state = MULTIPART_ACCUMULATE;
10717b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
10718b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10719b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Start a multi-part text value where we immediately push text data to a string
10720b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * value with the given selector. */
10721b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void multipart_start(upb_json_parser *p, upb_selector_t sel) {
10722b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert_accumulate_empty(p);
10723b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(p->multipart_state == MULTIPART_INACTIVE);
10724b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  p->multipart_state = MULTIPART_PUSHEAGERLY;
10725b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  p->string_selector = sel;
10726b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
10727b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10728b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool multipart_text(upb_json_parser *p, const char *buf, size_t len,
10729b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                           bool can_alias) {
10730b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  switch (p->multipart_state) {
10731b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case MULTIPART_INACTIVE:
10732b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_status_seterrmsg(
10733b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          &p->status, "Internal error: unexpected state MULTIPART_INACTIVE");
10734b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_env_reporterror(p->env, &p->status);
10735b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return false;
10736b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10737b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case MULTIPART_ACCUMULATE:
10738b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (!accumulate_append(p, buf, len, can_alias)) {
10739b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        return false;
10740b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
10741b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
10742b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10743b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case MULTIPART_PUSHEAGERLY: {
10744b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      const upb_bufhandle *handle = can_alias ? p->handle : NULL;
10745b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_sink_putstring(&p->top->sink, p->string_selector, buf, len, handle);
10746b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
10747b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
10748b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
10749b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10750b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
10751b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
10752b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10753b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Note: this invalidates the accumulate buffer!  Call only after reading its
10754b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * contents. */
10755b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void multipart_end(upb_json_parser *p) {
10756b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(p->multipart_state != MULTIPART_INACTIVE);
10757b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  p->multipart_state = MULTIPART_INACTIVE;
10758b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  accumulate_clear(p);
10759b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
10760b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10761b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10762b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Input capture **************************************************************/
10763b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10764b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Functionality for capturing a region of the input as text.  Gracefully
10765b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * handles the case where a buffer seam occurs in the middle of the captured
10766b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * region. */
10767b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10768b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void capture_begin(upb_json_parser *p, const char *ptr) {
10769b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(p->multipart_state != MULTIPART_INACTIVE);
10770b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(p->capture == NULL);
10771b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  p->capture = ptr;
10772b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
10773b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10774b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool capture_end(upb_json_parser *p, const char *ptr) {
10775b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(p->capture);
10776b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (multipart_text(p, p->capture, ptr - p->capture, true)) {
10777b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    p->capture = NULL;
10778b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return true;
10779b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
10780b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
10781b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
10782b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
10783b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10784b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* This is called at the end of each input buffer (ie. when we have hit a
10785b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * buffer seam).  If we are in the middle of capturing the input, this
10786b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * processes the unprocessed capture region. */
10787b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void capture_suspend(upb_json_parser *p, const char **ptr) {
10788b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!p->capture) return;
10789b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10790b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (multipart_text(p, p->capture, *ptr - p->capture, false)) {
10791b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* We use this as a signal that we were in the middle of capturing, and
10792b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * that capturing should resume at the beginning of the next buffer.
10793b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     *
10794b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * We can't use *ptr here, because we have no guarantee that this pointer
10795b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * will be valid when we resume (if the underlying memory is freed, then
10796b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * using the pointer at all, even to compare to NULL, is likely undefined
10797b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * behavior). */
10798b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    p->capture = &suspend_capture;
10799b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
10800b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Need to back up the pointer to the beginning of the capture, since
10801b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * we were not able to actually preserve it. */
10802b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    *ptr = p->capture;
10803b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
10804b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
10805b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10806b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void capture_resume(upb_json_parser *p, const char *ptr) {
10807b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (p->capture) {
10808b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    assert(p->capture == &suspend_capture);
10809b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    p->capture = ptr;
10810b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
10811b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
10812b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10813b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10814b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Callbacks from the parser **************************************************/
10815b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10816b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* These are the functions called directly from the parser itself.
10817b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * We define these in the same order as their declarations in the parser. */
10818b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10819b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic char escape_char(char in) {
10820b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  switch (in) {
10821b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case 'r': return '\r';
10822b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case 't': return '\t';
10823b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case 'n': return '\n';
10824b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case 'f': return '\f';
10825b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case 'b': return '\b';
10826b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case '/': return '/';
10827b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case '"': return '"';
10828b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case '\\': return '\\';
10829b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    default:
10830b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      assert(0);
10831b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return 'x';
10832b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
10833b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
10834b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10835b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool escape(upb_json_parser *p, const char *ptr) {
10836b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  char ch = escape_char(*ptr);
10837b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return multipart_text(p, &ch, 1, false);
10838b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
10839b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10840b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void start_hex(upb_json_parser *p) {
10841b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  p->digit = 0;
10842b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
10843b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10844b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void hexdigit(upb_json_parser *p, const char *ptr) {
10845b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  char ch = *ptr;
10846b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10847b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  p->digit <<= 4;
10848b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10849b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (ch >= '0' && ch <= '9') {
10850b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    p->digit += (ch - '0');
10851b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else if (ch >= 'a' && ch <= 'f') {
10852b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    p->digit += ((ch - 'a') + 10);
10853b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
10854b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    assert(ch >= 'A' && ch <= 'F');
10855b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    p->digit += ((ch - 'A') + 10);
10856b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
10857b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
10858b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10859b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool end_hex(upb_json_parser *p) {
10860b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  uint32_t codepoint = p->digit;
10861b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10862b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* emit the codepoint as UTF-8. */
10863b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  char utf8[3]; /* support \u0000 -- \uFFFF -- need only three bytes. */
10864b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  int length = 0;
10865b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (codepoint <= 0x7F) {
10866b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    utf8[0] = codepoint;
10867b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    length = 1;
10868b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else if (codepoint <= 0x07FF) {
10869b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    utf8[1] = (codepoint & 0x3F) | 0x80;
10870b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    codepoint >>= 6;
10871b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    utf8[0] = (codepoint & 0x1F) | 0xC0;
10872b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    length = 2;
10873b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else /* codepoint <= 0xFFFF */ {
10874b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    utf8[2] = (codepoint & 0x3F) | 0x80;
10875b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    codepoint >>= 6;
10876b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    utf8[1] = (codepoint & 0x3F) | 0x80;
10877b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    codepoint >>= 6;
10878b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    utf8[0] = (codepoint & 0x0F) | 0xE0;
10879b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    length = 3;
10880b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
10881b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* TODO(haberman): Handle high surrogates: if codepoint is a high surrogate
10882b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * we have to wait for the next escape to get the full code point). */
10883b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10884b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return multipart_text(p, utf8, length, false);
10885b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
10886b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10887b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void start_text(upb_json_parser *p, const char *ptr) {
10888b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  capture_begin(p, ptr);
10889b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
10890b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10891b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool end_text(upb_json_parser *p, const char *ptr) {
10892b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return capture_end(p, ptr);
10893b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
10894b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10895b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void start_number(upb_json_parser *p, const char *ptr) {
10896b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  multipart_startaccum(p);
10897b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  capture_begin(p, ptr);
10898b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
10899b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10900b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool parse_number(upb_json_parser *p);
10901b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10902b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool end_number(upb_json_parser *p, const char *ptr) {
10903b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!capture_end(p, ptr)) {
10904b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
10905b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
10906b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10907b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return parse_number(p);
10908b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
10909b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10910b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool parse_number(upb_json_parser *p) {
10911b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  size_t len;
10912b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const char *buf;
10913b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const char *myend;
10914b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  char *end;
10915b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10916b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* strtol() and friends unfortunately do not support specifying the length of
10917b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * the input string, so we need to force a copy into a NULL-terminated buffer. */
10918b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!multipart_text(p, "\0", 1, false)) {
10919b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
10920b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
10921b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10922b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  buf = accumulate_getptr(p, &len);
10923b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  myend = buf + len - 1;  /* One for NULL. */
10924b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10925b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* XXX: We are using strtol to parse integers, but this is wrong as even
10926b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * integers can be represented as 1e6 (for example), which strtol can't
10927b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * handle correctly.
10928b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   *
10929b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * XXX: Also, we can't handle large integers properly because strto[u]ll
10930b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * isn't in C89.
10931b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   *
10932b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * XXX: Also, we don't properly check floats for overflow, since strtof
10933b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * isn't in C89. */
10934b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  switch (upb_fielddef_type(p->top->f)) {
10935b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_ENUM:
10936b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_INT32: {
10937b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      long val = strtol(p->accumulated, &end, 0);
10938b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (val > INT32_MAX || val < INT32_MIN || errno == ERANGE || end != myend)
10939b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        goto err;
10940b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      else
10941b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_sink_putint32(&p->top->sink, parser_getsel(p), val);
10942b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
10943b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
10944b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_INT64: {
10945b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      long long val = strtol(p->accumulated, &end, 0);
10946b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (val > INT64_MAX || val < INT64_MIN || errno == ERANGE || end != myend)
10947b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        goto err;
10948b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      else
10949b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_sink_putint64(&p->top->sink, parser_getsel(p), val);
10950b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
10951b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
10952b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_UINT32: {
10953b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      unsigned long val = strtoul(p->accumulated, &end, 0);
10954b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (val > UINT32_MAX || errno == ERANGE || end != myend)
10955b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        goto err;
10956b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      else
10957b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_sink_putuint32(&p->top->sink, parser_getsel(p), val);
10958b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
10959b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
10960b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_UINT64: {
10961b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      unsigned long long val = strtoul(p->accumulated, &end, 0);
10962b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (val > UINT64_MAX || errno == ERANGE || end != myend)
10963b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        goto err;
10964b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      else
10965b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_sink_putuint64(&p->top->sink, parser_getsel(p), val);
10966b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
10967b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
10968b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_DOUBLE: {
10969b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      double val = strtod(p->accumulated, &end);
10970b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (errno == ERANGE || end != myend)
10971b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        goto err;
10972b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      else
10973b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_sink_putdouble(&p->top->sink, parser_getsel(p), val);
10974b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
10975b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
10976b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_FLOAT: {
10977b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      float val = strtod(p->accumulated, &end);
10978b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (errno == ERANGE || end != myend)
10979b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        goto err;
10980b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      else
10981b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_sink_putfloat(&p->top->sink, parser_getsel(p), val);
10982b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
10983b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
10984b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    default:
10985b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      assert(false);
10986b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
10987b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10988b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  multipart_end(p);
10989b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10990b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
10991b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10992b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammererr:
10993b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_status_seterrf(&p->status, "error parsing number: %s", buf);
10994b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_env_reporterror(p->env, &p->status);
10995b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  multipart_end(p);
10996b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return false;
10997b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
10998b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
10999b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool parser_putbool(upb_json_parser *p, bool val) {
11000b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bool ok;
11001b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11002b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upb_fielddef_type(p->top->f) != UPB_TYPE_BOOL) {
11003b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_status_seterrf(&p->status,
11004b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                       "Boolean value specified for non-bool field: %s",
11005b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                       upb_fielddef_name(p->top->f));
11006b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_env_reporterror(p->env, &p->status);
11007b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
11008b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
11009b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11010b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  ok = upb_sink_putbool(&p->top->sink, parser_getsel(p), val);
11011b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_ASSERT_VAR(ok, ok);
11012b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11013b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
11014b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
11015b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11016b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool start_stringval(upb_json_parser *p) {
11017b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(p->top->f);
11018b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11019b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upb_fielddef_isstring(p->top->f)) {
11020b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_jsonparser_frame *inner;
11021b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_selector_t sel;
11022b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11023b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (!check_stack(p)) return false;
11024b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11025b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Start a new parser frame: parser frames correspond one-to-one with
11026b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * handler frames, and string events occur in a sub-frame. */
11027b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    inner = p->top + 1;
11028b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSTR);
11029b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_sink_startstr(&p->top->sink, sel, 0, &inner->sink);
11030b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    inner->m = p->top->m;
11031b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    inner->f = p->top->f;
11032b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    inner->name_table = NULL;
11033b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    inner->is_map = false;
11034b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    inner->is_mapentry = false;
11035b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    p->top = inner;
11036b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11037b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (upb_fielddef_type(p->top->f) == UPB_TYPE_STRING) {
11038b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      /* For STRING fields we push data directly to the handlers as it is
11039b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer       * parsed.  We don't do this yet for BYTES fields, because our base64
11040b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer       * decoder is not streaming.
11041b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer       *
11042b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer       * TODO(haberman): make base64 decoding streaming also. */
11043b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      multipart_start(p, getsel_for_handlertype(p, UPB_HANDLER_STRING));
11044b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return true;
11045b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    } else {
11046b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      multipart_startaccum(p);
11047b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return true;
11048b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
11049b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else if (upb_fielddef_type(p->top->f) == UPB_TYPE_ENUM) {
11050b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* No need to push a frame -- symbolic enum names in quotes remain in the
11051b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * current parser frame.
11052b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     *
11053b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * Enum string values must accumulate so we can look up the value in a table
11054b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * once it is complete. */
11055b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    multipart_startaccum(p);
11056b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return true;
11057b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
11058b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_status_seterrf(&p->status,
11059b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                       "String specified for non-string/non-enum field: %s",
11060b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                       upb_fielddef_name(p->top->f));
11061b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_env_reporterror(p->env, &p->status);
11062b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
11063b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
11064b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
11065b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11066b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool end_stringval(upb_json_parser *p) {
11067b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bool ok = true;
11068b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11069b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  switch (upb_fielddef_type(p->top->f)) {
11070b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_BYTES:
11071b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (!base64_push(p, getsel_for_handlertype(p, UPB_HANDLER_STRING),
11072b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                       p->accumulated, p->accumulated_len)) {
11073b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        return false;
11074b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
11075b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      /* Fall through. */
11076b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11077b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_STRING: {
11078b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR);
11079b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_sink_endstr(&p->top->sink, sel);
11080b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      p->top--;
11081b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
11082b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
11083b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11084b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_ENUM: {
11085b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      /* Resolve enum symbolic name to integer value. */
11086b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      const upb_enumdef *enumdef =
11087b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          (const upb_enumdef*)upb_fielddef_subdef(p->top->f);
11088b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11089b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      size_t len;
11090b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      const char *buf = accumulate_getptr(p, &len);
11091b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11092b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      int32_t int_val = 0;
11093b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      ok = upb_enumdef_ntoi(enumdef, buf, len, &int_val);
11094b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11095b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (ok) {
11096b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_selector_t sel = parser_getsel(p);
11097b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_sink_putint32(&p->top->sink, sel, int_val);
11098b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      } else {
11099b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_status_seterrf(&p->status, "Enum value unknown: '%.*s'", len, buf);
11100b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_env_reporterror(p->env, &p->status);
11101b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
11102b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11103b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
11104b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
11105b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11106b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    default:
11107b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      assert(false);
11108b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_status_seterrmsg(&p->status, "Internal error in JSON decoder");
11109b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_env_reporterror(p->env, &p->status);
11110b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      ok = false;
11111b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
11112b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
11113b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11114b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  multipart_end(p);
11115b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11116b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return ok;
11117b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
11118b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11119b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void start_member(upb_json_parser *p) {
11120b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(!p->top->f);
11121b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  multipart_startaccum(p);
11122b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
11123b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11124b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Helper: invoked during parse_mapentry() to emit the mapentry message's key
11125b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * field based on the current contents of the accumulate buffer. */
11126b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool parse_mapentry_key(upb_json_parser *p) {
11127b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11128b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  size_t len;
11129b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const char *buf = accumulate_getptr(p, &len);
11130b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11131b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Emit the key field. We do a bit of ad-hoc parsing here because the
11132b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * parser state machine has already decided that this is a string field
11133b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * name, and we are reinterpreting it as some arbitrary key type. In
11134b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * particular, integer and bool keys are quoted, so we need to parse the
11135b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * quoted string contents here. */
11136b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11137b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  p->top->f = upb_msgdef_itof(p->top->m, UPB_MAPENTRY_KEY);
11138b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (p->top->f == NULL) {
11139b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_status_seterrmsg(&p->status, "mapentry message has no key");
11140b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_env_reporterror(p->env, &p->status);
11141b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
11142b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
11143b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  switch (upb_fielddef_type(p->top->f)) {
11144b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_INT32:
11145b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_INT64:
11146b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_UINT32:
11147b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_UINT64:
11148b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      /* Invoke end_number. The accum buffer has the number's text already. */
11149b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (!parse_number(p)) {
11150b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        return false;
11151b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
11152b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
11153b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_BOOL:
11154b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (len == 4 && !strncmp(buf, "true", 4)) {
11155b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        if (!parser_putbool(p, true)) {
11156b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          return false;
11157b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        }
11158b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      } else if (len == 5 && !strncmp(buf, "false", 5)) {
11159b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        if (!parser_putbool(p, false)) {
11160b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          return false;
11161b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        }
11162b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      } else {
11163b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_status_seterrmsg(&p->status,
11164b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                             "Map bool key not 'true' or 'false'");
11165b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_env_reporterror(p->env, &p->status);
11166b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        return false;
11167b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
11168b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      multipart_end(p);
11169b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
11170b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_STRING:
11171b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_BYTES: {
11172b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_sink subsink;
11173b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSTR);
11174b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_sink_startstr(&p->top->sink, sel, len, &subsink);
11175b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      sel = getsel_for_handlertype(p, UPB_HANDLER_STRING);
11176b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_sink_putstring(&subsink, sel, buf, len, NULL);
11177b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR);
11178b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_sink_endstr(&subsink, sel);
11179b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      multipart_end(p);
11180b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
11181b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
11182b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    default:
11183b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_status_seterrmsg(&p->status, "Invalid field type for map key");
11184b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_env_reporterror(p->env, &p->status);
11185b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return false;
11186b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
11187b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11188b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
11189b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
11190b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11191b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Helper: emit one map entry (as a submessage in the map field sequence). This
11192b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * is invoked from end_membername(), at the end of the map entry's key string,
11193b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * with the map key in the accumulate buffer. It parses the key from that
11194b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * buffer, emits the handler calls to start the mapentry submessage (setting up
11195b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * its subframe in the process), and sets up state in the subframe so that the
11196b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * value parser (invoked next) will emit the mapentry's value field and then
11197b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * end the mapentry message. */
11198b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11199b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool handle_mapentry(upb_json_parser *p) {
11200b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const upb_fielddef *mapfield;
11201b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const upb_msgdef *mapentrymsg;
11202b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_jsonparser_frame *inner;
11203b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_selector_t sel;
11204b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11205b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Map entry: p->top->sink is the seq frame, so we need to start a frame
11206b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * for the mapentry itself, and then set |f| in that frame so that the map
11207b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * value field is parsed, and also set a flag to end the frame after the
11208b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * map-entry value is parsed. */
11209b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!check_stack(p)) return false;
11210b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11211b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  mapfield = p->top->mapfield;
11212b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  mapentrymsg = upb_fielddef_msgsubdef(mapfield);
11213b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11214b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  inner = p->top + 1;
11215b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  p->top->f = mapfield;
11216b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSUBMSG);
11217b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_sink_startsubmsg(&p->top->sink, sel, &inner->sink);
11218b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  inner->m = mapentrymsg;
11219b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  inner->name_table = NULL;
11220b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  inner->mapfield = mapfield;
11221b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  inner->is_map = false;
11222b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11223b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Don't set this to true *yet* -- we reuse parsing handlers below to push
11224b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * the key field value to the sink, and these handlers will pop the frame
11225b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * if they see is_mapentry (when invoked by the parser state machine, they
11226b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * would have just seen the map-entry value, not key). */
11227b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  inner->is_mapentry = false;
11228b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  p->top = inner;
11229b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11230b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* send STARTMSG in submsg frame. */
11231b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_sink_startmsg(&p->top->sink);
11232b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11233b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  parse_mapentry_key(p);
11234b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11235b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Set up the value field to receive the map-entry value. */
11236b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  p->top->f = upb_msgdef_itof(p->top->m, UPB_MAPENTRY_VALUE);
11237b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  p->top->is_mapentry = true;  /* set up to pop frame after value is parsed. */
11238b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  p->top->mapfield = mapfield;
11239b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (p->top->f == NULL) {
11240b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_status_seterrmsg(&p->status, "mapentry message has no value");
11241b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_env_reporterror(p->env, &p->status);
11242b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
11243b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
11244b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11245b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
11246b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
11247b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11248b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool end_membername(upb_json_parser *p) {
11249b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(!p->top->f);
11250b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11251b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (p->top->is_map) {
11252b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return handle_mapentry(p);
11253b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
11254b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    size_t len;
11255b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    const char *buf = accumulate_getptr(p, &len);
11256b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_value v;
11257b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11258b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (upb_strtable_lookup2(p->top->name_table, buf, len, &v)) {
11259b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      p->top->f = upb_value_getconstptr(v);
11260b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      multipart_end(p);
11261b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11262b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return true;
11263b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    } else {
11264b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      /* TODO(haberman): Ignore unknown fields if requested/configured to do
11265b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer       * so. */
11266b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_status_seterrf(&p->status, "No such field: %.*s\n", (int)len, buf);
11267b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_env_reporterror(p->env, &p->status);
11268b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return false;
11269b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
11270b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
11271b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
11272b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11273b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void end_member(upb_json_parser *p) {
11274b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* If we just parsed a map-entry value, end that frame too. */
11275b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (p->top->is_mapentry) {
11276b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_status s = UPB_STATUS_INIT;
11277b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_selector_t sel;
11278b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    bool ok;
11279b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    const upb_fielddef *mapfield;
11280b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11281b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    assert(p->top > p->stack);
11282b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* send ENDMSG on submsg. */
11283b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_sink_endmsg(&p->top->sink, &s);
11284b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    mapfield = p->top->mapfield;
11285b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11286b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* send ENDSUBMSG in repeated-field-of-mapentries frame. */
11287b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    p->top--;
11288b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    ok = upb_handlers_getselector(mapfield, UPB_HANDLER_ENDSUBMSG, &sel);
11289b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    UPB_ASSERT_VAR(ok, ok);
11290b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_sink_endsubmsg(&p->top->sink, sel);
11291b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
11292b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11293b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  p->top->f = NULL;
11294b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
11295b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11296b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool start_subobject(upb_json_parser *p) {
11297b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(p->top->f);
11298b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11299b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upb_fielddef_ismap(p->top->f)) {
11300b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_jsonparser_frame *inner;
11301b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_selector_t sel;
11302b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11303b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Beginning of a map. Start a new parser frame in a repeated-field
11304b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * context. */
11305b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (!check_stack(p)) return false;
11306b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11307b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    inner = p->top + 1;
11308b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSEQ);
11309b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_sink_startseq(&p->top->sink, sel, &inner->sink);
11310b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    inner->m = upb_fielddef_msgsubdef(p->top->f);
11311b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    inner->name_table = NULL;
11312b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    inner->mapfield = p->top->f;
11313b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    inner->f = NULL;
11314b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    inner->is_map = true;
11315b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    inner->is_mapentry = false;
11316b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    p->top = inner;
11317b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11318b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return true;
11319b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else if (upb_fielddef_issubmsg(p->top->f)) {
11320b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_jsonparser_frame *inner;
11321b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_selector_t sel;
11322b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11323b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Beginning of a subobject. Start a new parser frame in the submsg
11324b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * context. */
11325b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (!check_stack(p)) return false;
11326b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11327b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    inner = p->top + 1;
11328b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11329b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSUBMSG);
11330b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_sink_startsubmsg(&p->top->sink, sel, &inner->sink);
11331b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    inner->m = upb_fielddef_msgsubdef(p->top->f);
11332b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    set_name_table(p, inner);
11333b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    inner->f = NULL;
11334b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    inner->is_map = false;
11335b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    inner->is_mapentry = false;
11336b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    p->top = inner;
11337b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11338b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return true;
11339b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
11340b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_status_seterrf(&p->status,
11341b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                       "Object specified for non-message/group field: %s",
11342b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                       upb_fielddef_name(p->top->f));
11343b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_env_reporterror(p->env, &p->status);
11344b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
11345b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
11346b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
11347b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11348b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void end_subobject(upb_json_parser *p) {
11349b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (p->top->is_map) {
11350b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_selector_t sel;
11351b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    p->top--;
11352b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSEQ);
11353b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_sink_endseq(&p->top->sink, sel);
11354b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
11355b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_selector_t sel;
11356b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    p->top--;
11357b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSUBMSG);
11358b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_sink_endsubmsg(&p->top->sink, sel);
11359b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
11360b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
11361b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11362b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool start_array(upb_json_parser *p) {
11363b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_jsonparser_frame *inner;
11364b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_selector_t sel;
11365b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11366b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(p->top->f);
11367b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11368b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!upb_fielddef_isseq(p->top->f)) {
11369b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_status_seterrf(&p->status,
11370b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                       "Array specified for non-repeated field: %s",
11371b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                       upb_fielddef_name(p->top->f));
11372b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_env_reporterror(p->env, &p->status);
11373b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return false;
11374b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
11375b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11376b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!check_stack(p)) return false;
11377b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11378b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  inner = p->top + 1;
11379b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSEQ);
11380b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_sink_startseq(&p->top->sink, sel, &inner->sink);
11381b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  inner->m = p->top->m;
11382b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  inner->name_table = NULL;
11383b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  inner->f = p->top->f;
11384b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  inner->is_map = false;
11385b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  inner->is_mapentry = false;
11386b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  p->top = inner;
11387b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11388b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
11389b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
11390b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11391b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void end_array(upb_json_parser *p) {
11392b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_selector_t sel;
11393b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11394b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(p->top > p->stack);
11395b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11396b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  p->top--;
11397b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSEQ);
11398b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_sink_endseq(&p->top->sink, sel);
11399b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
11400b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11401b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void start_object(upb_json_parser *p) {
11402b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!p->top->is_map) {
11403b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_sink_startmsg(&p->top->sink);
11404b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
11405b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
11406b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11407b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void end_object(upb_json_parser *p) {
11408b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!p->top->is_map) {
11409b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_status status;
11410b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_status_clear(&status);
11411b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_sink_endmsg(&p->top->sink, &status);
11412b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (!upb_ok(&status)) {
11413b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_env_reporterror(p->env, &status);
11414b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
11415b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
11416b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
11417b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11418b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11419b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#define CHECK_RETURN_TOP(x) if (!(x)) goto error
11420b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11421b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11422b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* The actual parser **********************************************************/
11423b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11424b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* What follows is the Ragel parser itself.  The language is specified in Ragel
11425b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * and the actions call our C functions above.
11426b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *
11427b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Ragel has an extensive set of functionality, and we use only a small part of
11428b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * it.  There are many action types but we only use a few:
11429b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *
11430b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *   ">" -- transition into a machine
11431b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *   "%" -- transition out of a machine
11432b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *   "@" -- transition into a final state of a machine.
11433b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *
11434b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * "@" transitions are tricky because a machine can transition into a final
11435b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * state repeatedly.  But in some cases we know this can't happen, for example
11436b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * a string which is delimited by a final '"' can only transition into its
11437b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * final state once, when the closing '"' is seen. */
11438b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11439b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11440b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#line 1245 "upb/json/parser.rl"
11441b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11442b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11443b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11444b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#line 1157 "upb/json/parser.c"
11445b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic const char _json_actions[] = {
11446b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	0, 1, 0, 1, 2, 1, 3, 1,
11447b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	5, 1, 6, 1, 7, 1, 8, 1,
11448b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	10, 1, 12, 1, 13, 1, 14, 1,
11449b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	15, 1, 16, 1, 17, 1, 21, 1,
11450b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	25, 1, 27, 2, 3, 8, 2, 4,
11451b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	5, 2, 6, 2, 2, 6, 8, 2,
11452b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	11, 9, 2, 13, 15, 2, 14, 15,
11453b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	2, 18, 1, 2, 19, 27, 2, 20,
11454b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	9, 2, 22, 27, 2, 23, 27, 2,
11455b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	24, 27, 2, 26, 27, 3, 14, 11,
11456b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	9
11457b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer};
11458b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11459b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic const unsigned char _json_key_offsets[] = {
11460b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	0, 0, 4, 9, 14, 15, 19, 24,
11461b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	29, 34, 38, 42, 45, 48, 50, 54,
11462b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	58, 60, 62, 67, 69, 71, 80, 86,
11463b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	92, 98, 104, 106, 115, 116, 116, 116,
11464b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	121, 126, 131, 132, 133, 134, 135, 135,
11465b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	136, 137, 138, 138, 139, 140, 141, 141,
11466b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	146, 151, 152, 156, 161, 166, 171, 175,
11467b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	175, 178, 178, 178
11468b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer};
11469b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11470b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic const char _json_trans_keys[] = {
11471b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	32, 123, 9, 13, 32, 34, 125, 9,
11472b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	13, 32, 34, 125, 9, 13, 34, 32,
11473b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	58, 9, 13, 32, 93, 125, 9, 13,
11474b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	32, 44, 125, 9, 13, 32, 44, 125,
11475b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	9, 13, 32, 34, 9, 13, 45, 48,
11476b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	49, 57, 48, 49, 57, 46, 69, 101,
11477b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	48, 57, 69, 101, 48, 57, 43, 45,
11478b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	48, 57, 48, 57, 48, 57, 46, 69,
11479b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	101, 48, 57, 34, 92, 34, 92, 34,
11480b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	47, 92, 98, 102, 110, 114, 116, 117,
11481b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	48, 57, 65, 70, 97, 102, 48, 57,
11482b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	65, 70, 97, 102, 48, 57, 65, 70,
11483b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	97, 102, 48, 57, 65, 70, 97, 102,
11484b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	34, 92, 34, 45, 91, 102, 110, 116,
11485b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	123, 48, 57, 34, 32, 93, 125, 9,
11486b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	13, 32, 44, 93, 9, 13, 32, 93,
11487b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	125, 9, 13, 97, 108, 115, 101, 117,
11488b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	108, 108, 114, 117, 101, 32, 34, 125,
11489b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	9, 13, 32, 34, 125, 9, 13, 34,
11490b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	32, 58, 9, 13, 32, 93, 125, 9,
11491b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	13, 32, 44, 125, 9, 13, 32, 44,
11492b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	125, 9, 13, 32, 34, 9, 13, 32,
11493b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	9, 13, 0
11494b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer};
11495b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11496b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic const char _json_single_lengths[] = {
11497b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	0, 2, 3, 3, 1, 2, 3, 3,
11498b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	3, 2, 2, 1, 3, 0, 2, 2,
11499b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	0, 0, 3, 2, 2, 9, 0, 0,
11500b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	0, 0, 2, 7, 1, 0, 0, 3,
11501b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	3, 3, 1, 1, 1, 1, 0, 1,
11502b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	1, 1, 0, 1, 1, 1, 0, 3,
11503b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	3, 1, 2, 3, 3, 3, 2, 0,
11504b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	1, 0, 0, 0
11505b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer};
11506b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11507b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic const char _json_range_lengths[] = {
11508b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	0, 1, 1, 1, 0, 1, 1, 1,
11509b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	1, 1, 1, 1, 0, 1, 1, 1,
11510b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	1, 1, 1, 0, 0, 0, 3, 3,
11511b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	3, 3, 0, 1, 0, 0, 0, 1,
11512b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	1, 1, 0, 0, 0, 0, 0, 0,
11513b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	0, 0, 0, 0, 0, 0, 0, 1,
11514b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	1, 0, 1, 1, 1, 1, 1, 0,
11515b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	1, 0, 0, 0
11516b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer};
11517b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11518b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic const short _json_index_offsets[] = {
11519b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	0, 0, 4, 9, 14, 16, 20, 25,
11520b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	30, 35, 39, 43, 46, 50, 52, 56,
11521b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	60, 62, 64, 69, 72, 75, 85, 89,
11522b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	93, 97, 101, 104, 113, 115, 116, 117,
11523b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	122, 127, 132, 134, 136, 138, 140, 141,
11524b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	143, 145, 147, 148, 150, 152, 154, 155,
11525b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	160, 165, 167, 171, 176, 181, 186, 190,
11526b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	191, 194, 195, 196
11527b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer};
11528b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11529b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic const char _json_indicies[] = {
11530b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	0, 2, 0, 1, 3, 4, 5, 3,
11531b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	1, 6, 7, 8, 6, 1, 9, 1,
11532b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	10, 11, 10, 1, 11, 1, 1, 11,
11533b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	12, 13, 14, 15, 13, 1, 16, 17,
11534b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	8, 16, 1, 17, 7, 17, 1, 18,
11535b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	19, 20, 1, 19, 20, 1, 22, 23,
11536b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	23, 21, 24, 1, 23, 23, 24, 21,
11537b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	25, 25, 26, 1, 26, 1, 26, 21,
11538b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	22, 23, 23, 20, 21, 28, 29, 27,
11539b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	31, 32, 30, 33, 33, 33, 33, 33,
11540b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	33, 33, 33, 34, 1, 35, 35, 35,
11541b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	1, 36, 36, 36, 1, 37, 37, 37,
11542b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	1, 38, 38, 38, 1, 40, 41, 39,
11543b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	42, 43, 44, 45, 46, 47, 48, 43,
11544b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	1, 49, 1, 50, 51, 53, 54, 1,
11545b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	53, 52, 55, 56, 54, 55, 1, 56,
11546b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	1, 1, 56, 52, 57, 1, 58, 1,
11547b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	59, 1, 60, 1, 61, 62, 1, 63,
11548b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	1, 64, 1, 65, 66, 1, 67, 1,
11549b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	68, 1, 69, 70, 71, 72, 70, 1,
11550b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	73, 74, 75, 73, 1, 76, 1, 77,
11551b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	78, 77, 1, 78, 1, 1, 78, 79,
11552b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	80, 81, 82, 80, 1, 83, 84, 75,
11553b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	83, 1, 84, 74, 84, 1, 85, 86,
11554b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	86, 1, 1, 1, 1, 0
11555b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer};
11556b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11557b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic const char _json_trans_targs[] = {
11558b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	1, 0, 2, 3, 4, 56, 3, 4,
11559b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	56, 5, 5, 6, 7, 8, 9, 56,
11560b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	8, 9, 11, 12, 18, 57, 13, 15,
11561b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	14, 16, 17, 20, 58, 21, 20, 58,
11562b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	21, 19, 22, 23, 24, 25, 26, 20,
11563b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	58, 21, 28, 30, 31, 34, 39, 43,
11564b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	47, 29, 59, 59, 32, 31, 29, 32,
11565b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	33, 35, 36, 37, 38, 59, 40, 41,
11566b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	42, 59, 44, 45, 46, 59, 48, 49,
11567b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	55, 48, 49, 55, 50, 50, 51, 52,
11568b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	53, 54, 55, 53, 54, 59, 56
11569b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer};
11570b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11571b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic const char _json_trans_actions[] = {
11572b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	0, 0, 0, 21, 77, 53, 0, 47,
11573b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	23, 17, 0, 0, 15, 19, 19, 50,
11574b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	0, 0, 0, 0, 0, 1, 0, 0,
11575b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	0, 0, 0, 3, 13, 0, 0, 35,
11576b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	5, 11, 0, 38, 7, 7, 7, 41,
11577b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	44, 9, 62, 56, 25, 0, 0, 0,
11578b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	31, 29, 33, 59, 15, 0, 27, 0,
11579b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	0, 0, 0, 0, 0, 68, 0, 0,
11580b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	0, 71, 0, 0, 0, 65, 21, 77,
11581b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	53, 0, 47, 23, 17, 0, 0, 15,
11582b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	19, 19, 50, 0, 0, 74, 0
11583b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer};
11584b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11585b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic const int json_start = 1;
11586b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11587b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic const int json_en_number_machine = 10;
11588b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic const int json_en_string_machine = 19;
11589b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic const int json_en_value_machine = 27;
11590b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic const int json_en_main = 1;
11591b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11592b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11593b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#line 1248 "upb/json/parser.rl"
11594b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11595b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammersize_t parse(void *closure, const void *hd, const char *buf, size_t size,
11596b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer             const upb_bufhandle *handle) {
11597b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_json_parser *parser = closure;
11598b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11599b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Variables used by Ragel's generated code. */
11600b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  int cs = parser->current_state;
11601b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  int *stack = parser->parser_stack;
11602b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  int top = parser->parser_top;
11603b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11604b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const char *p = buf;
11605b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const char *pe = buf + size;
11606b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11607b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  parser->handle = handle;
11608b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11609b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(hd);
11610b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(handle);
11611b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11612b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  capture_resume(parser, buf);
11613b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11614b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11615b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#line 1328 "upb/json/parser.c"
11616b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	{
11617b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	int _klen;
11618b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	unsigned int _trans;
11619b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	const char *_acts;
11620b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	unsigned int _nacts;
11621b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	const char *_keys;
11622b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11623b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	if ( p == pe )
11624b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer		goto _test_eof;
11625b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	if ( cs == 0 )
11626b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer		goto _out;
11627b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer_resume:
11628b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	_keys = _json_trans_keys + _json_key_offsets[cs];
11629b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	_trans = _json_index_offsets[cs];
11630b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11631b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	_klen = _json_single_lengths[cs];
11632b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	if ( _klen > 0 ) {
11633b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer		const char *_lower = _keys;
11634b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer		const char *_mid;
11635b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer		const char *_upper = _keys + _klen - 1;
11636b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer		while (1) {
11637b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer			if ( _upper < _lower )
11638b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer				break;
11639b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11640b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer			_mid = _lower + ((_upper-_lower) >> 1);
11641b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer			if ( (*p) < *_mid )
11642b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer				_upper = _mid - 1;
11643b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer			else if ( (*p) > *_mid )
11644b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer				_lower = _mid + 1;
11645b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer			else {
11646b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer				_trans += (unsigned int)(_mid - _keys);
11647b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer				goto _match;
11648b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer			}
11649b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer		}
11650b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer		_keys += _klen;
11651b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer		_trans += _klen;
11652b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	}
11653b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11654b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	_klen = _json_range_lengths[cs];
11655b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	if ( _klen > 0 ) {
11656b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer		const char *_lower = _keys;
11657b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer		const char *_mid;
11658b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer		const char *_upper = _keys + (_klen<<1) - 2;
11659b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer		while (1) {
11660b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer			if ( _upper < _lower )
11661b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer				break;
11662b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11663b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer			_mid = _lower + (((_upper-_lower) >> 1) & ~1);
11664b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer			if ( (*p) < _mid[0] )
11665b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer				_upper = _mid - 2;
11666b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer			else if ( (*p) > _mid[1] )
11667b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer				_lower = _mid + 2;
11668b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer			else {
11669b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer				_trans += (unsigned int)((_mid - _keys)>>1);
11670b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer				goto _match;
11671b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer			}
11672b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer		}
11673b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer		_trans += _klen;
11674b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	}
11675b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11676b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer_match:
11677b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	_trans = _json_indicies[_trans];
11678b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	cs = _json_trans_targs[_trans];
11679b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11680b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	if ( _json_trans_actions[_trans] == 0 )
11681b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer		goto _again;
11682b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11683b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	_acts = _json_actions + _json_trans_actions[_trans];
11684b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	_nacts = (unsigned int) *_acts++;
11685b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	while ( _nacts-- > 0 )
11686b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	{
11687b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer		switch ( *_acts++ )
11688b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer		{
11689b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	case 0:
11690b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#line 1160 "upb/json/parser.rl"
11691b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	{ p--; {cs = stack[--top]; goto _again;} }
11692b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	break;
11693b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	case 1:
11694b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#line 1161 "upb/json/parser.rl"
11695b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	{ p--; {stack[top++] = cs; cs = 10; goto _again;} }
11696b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	break;
11697b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	case 2:
11698b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#line 1165 "upb/json/parser.rl"
11699b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	{ start_text(parser, p); }
11700b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	break;
11701b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	case 3:
11702b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#line 1166 "upb/json/parser.rl"
11703b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	{ CHECK_RETURN_TOP(end_text(parser, p)); }
11704b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	break;
11705b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	case 4:
11706b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#line 1172 "upb/json/parser.rl"
11707b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	{ start_hex(parser); }
11708b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	break;
11709b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	case 5:
11710b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#line 1173 "upb/json/parser.rl"
11711b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	{ hexdigit(parser, p); }
11712b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	break;
11713b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	case 6:
11714b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#line 1174 "upb/json/parser.rl"
11715b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	{ CHECK_RETURN_TOP(end_hex(parser)); }
11716b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	break;
11717b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	case 7:
11718b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#line 1180 "upb/json/parser.rl"
11719b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	{ CHECK_RETURN_TOP(escape(parser, p)); }
11720b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	break;
11721b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	case 8:
11722b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#line 1186 "upb/json/parser.rl"
11723b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	{ p--; {cs = stack[--top]; goto _again;} }
11724b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	break;
11725b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	case 9:
11726b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#line 1189 "upb/json/parser.rl"
11727b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	{ {stack[top++] = cs; cs = 19; goto _again;} }
11728b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	break;
11729b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	case 10:
11730b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#line 1191 "upb/json/parser.rl"
11731b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	{ p--; {stack[top++] = cs; cs = 27; goto _again;} }
11732b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	break;
11733b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	case 11:
11734b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#line 1196 "upb/json/parser.rl"
11735b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	{ start_member(parser); }
11736b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	break;
11737b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	case 12:
11738b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#line 1197 "upb/json/parser.rl"
11739b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	{ CHECK_RETURN_TOP(end_membername(parser)); }
11740b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	break;
11741b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	case 13:
11742b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#line 1200 "upb/json/parser.rl"
11743b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	{ end_member(parser); }
11744b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	break;
11745b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	case 14:
11746b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#line 1206 "upb/json/parser.rl"
11747b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	{ start_object(parser); }
11748b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	break;
11749b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	case 15:
11750b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#line 1209 "upb/json/parser.rl"
11751b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	{ end_object(parser); }
11752b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	break;
11753b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	case 16:
11754b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#line 1215 "upb/json/parser.rl"
11755b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	{ CHECK_RETURN_TOP(start_array(parser)); }
11756b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	break;
11757b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	case 17:
11758b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#line 1219 "upb/json/parser.rl"
11759b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	{ end_array(parser); }
11760b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	break;
11761b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	case 18:
11762b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#line 1224 "upb/json/parser.rl"
11763b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	{ start_number(parser, p); }
11764b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	break;
11765b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	case 19:
11766b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#line 1225 "upb/json/parser.rl"
11767b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	{ CHECK_RETURN_TOP(end_number(parser, p)); }
11768b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	break;
11769b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	case 20:
11770b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#line 1227 "upb/json/parser.rl"
11771b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	{ CHECK_RETURN_TOP(start_stringval(parser)); }
11772b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	break;
11773b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	case 21:
11774b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#line 1228 "upb/json/parser.rl"
11775b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	{ CHECK_RETURN_TOP(end_stringval(parser)); }
11776b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	break;
11777b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	case 22:
11778b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#line 1230 "upb/json/parser.rl"
11779b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	{ CHECK_RETURN_TOP(parser_putbool(parser, true)); }
11780b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	break;
11781b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	case 23:
11782b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#line 1232 "upb/json/parser.rl"
11783b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	{ CHECK_RETURN_TOP(parser_putbool(parser, false)); }
11784b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	break;
11785b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	case 24:
11786b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#line 1234 "upb/json/parser.rl"
11787b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	{ /* null value */ }
11788b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	break;
11789b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	case 25:
11790b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#line 1236 "upb/json/parser.rl"
11791b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	{ CHECK_RETURN_TOP(start_subobject(parser)); }
11792b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	break;
11793b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	case 26:
11794b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#line 1237 "upb/json/parser.rl"
11795b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	{ end_subobject(parser); }
11796b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	break;
11797b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	case 27:
11798b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#line 1242 "upb/json/parser.rl"
11799b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	{ p--; {cs = stack[--top]; goto _again;} }
11800b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	break;
11801b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#line 1514 "upb/json/parser.c"
11802b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer		}
11803b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	}
11804b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11805b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer_again:
11806b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	if ( cs == 0 )
11807b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer		goto _out;
11808b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	if ( ++p != pe )
11809b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer		goto _resume;
11810b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	_test_eof: {}
11811b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	_out: {}
11812b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	}
11813b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11814b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#line 1269 "upb/json/parser.rl"
11815b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11816b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (p != pe) {
11817b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_status_seterrf(&parser->status, "Parse error at '%.*s'\n", pe - p, p);
11818b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_env_reporterror(parser->env, &parser->status);
11819b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
11820b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    capture_suspend(parser, &p);
11821b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
11822b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11823b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammererror:
11824b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Save parsing state back to parser. */
11825b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  parser->current_state = cs;
11826b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  parser->parser_top = top;
11827b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11828b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return p - buf;
11829b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
11830b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11831b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerbool end(void *closure, const void *hd) {
11832b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(closure);
11833b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(hd);
11834b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11835b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Prevent compile warning on unused static constants. */
11836b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(json_start);
11837b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(json_en_number_machine);
11838b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(json_en_string_machine);
11839b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(json_en_value_machine);
11840b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(json_en_main);
11841b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
11842b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
11843b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11844b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void json_parser_reset(upb_json_parser *p) {
11845b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  int cs;
11846b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  int top;
11847b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11848b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  p->top = p->stack;
11849b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  p->top->f = NULL;
11850b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  p->top->is_map = false;
11851b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  p->top->is_mapentry = false;
11852b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11853b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Emit Ragel initialization of the parser. */
11854b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11855b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#line 1568 "upb/json/parser.c"
11856b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	{
11857b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	cs = json_start;
11858b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	top = 0;
11859b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer	}
11860b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11861b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#line 1309 "upb/json/parser.rl"
11862b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  p->current_state = cs;
11863b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  p->parser_top = top;
11864b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  accumulate_clear(p);
11865b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  p->multipart_state = MULTIPART_INACTIVE;
11866b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  p->capture = NULL;
11867b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  p->accumulated = NULL;
11868b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_status_clear(&p->status);
11869b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
11870b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11871b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void visit_json_parsermethod(const upb_refcounted *r,
11872b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                    upb_refcounted_visit *visit,
11873b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                    void *closure) {
11874b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const upb_json_parsermethod *method = (upb_json_parsermethod*)r;
11875b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  visit(r, upb_msgdef_upcast2(method->msg), closure);
11876b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
11877b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11878b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void free_json_parsermethod(upb_refcounted *r) {
11879b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_json_parsermethod *method = (upb_json_parsermethod*)r;
11880b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11881b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_iter i;
11882b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_begin(&i, &method->name_tables);
11883b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
11884b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_value val = upb_inttable_iter_value(&i);
11885b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_strtable *t = upb_value_getptr(val);
11886b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_strtable_uninit(t);
11887b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_gfree(t);
11888b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
11889b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11890b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_uninit(&method->name_tables);
11891b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11892b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_gfree(r);
11893b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
11894b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11895b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void add_jsonname_table(upb_json_parsermethod *m, const upb_msgdef* md) {
11896b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_msg_field_iter i;
11897b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_strtable *t;
11898b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11899b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* It would be nice to stack-allocate this, but protobufs do not limit the
11900b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * length of fields to any reasonable limit. */
11901b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  char *buf = NULL;
11902b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  size_t len = 0;
11903b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11904b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (upb_inttable_lookupptr(&m->name_tables, md, NULL)) {
11905b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return;
11906b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
11907b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11908b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* TODO(haberman): handle malloc failure. */
11909b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  t = upb_gmalloc(sizeof(*t));
11910b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_strtable_init(t, UPB_CTYPE_CONSTPTR);
11911b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_insertptr(&m->name_tables, md, upb_value_ptr(t));
11912b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11913b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for(upb_msg_field_begin(&i, md);
11914b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      !upb_msg_field_done(&i);
11915b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_msg_field_next(&i)) {
11916b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    const upb_fielddef *f = upb_msg_iter_field(&i);
11917b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11918b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Add an entry for the JSON name. */
11919b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    size_t field_len = upb_fielddef_getjsonname(f, buf, len);
11920b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (field_len > len) {
11921b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      size_t len2;
11922b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      buf = upb_grealloc(buf, 0, field_len);
11923b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      len = field_len;
11924b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      len2 = upb_fielddef_getjsonname(f, buf, len);
11925b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      UPB_ASSERT_VAR(len2, len == len2);
11926b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
11927b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_strtable_insert(t, buf, upb_value_constptr(f));
11928b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11929b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (strcmp(buf, upb_fielddef_name(f)) != 0) {
11930b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      /* Since the JSON name is different from the regular field name, add an
11931b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer       * entry for the raw name (compliant proto3 JSON parsers must accept
11932b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer       * both). */
11933b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_strtable_insert(t, upb_fielddef_name(f), upb_value_constptr(f));
11934b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
11935b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11936b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (upb_fielddef_issubmsg(f)) {
11937b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      add_jsonname_table(m, upb_fielddef_msgsubdef(f));
11938b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
11939b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
11940b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11941b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_gfree(buf);
11942b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
11943b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11944b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Public API *****************************************************************/
11945b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11946b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerupb_json_parser *upb_json_parser_create(upb_env *env,
11947b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                        const upb_json_parsermethod *method,
11948b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                        upb_sink *output) {
11949b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#ifndef NDEBUG
11950b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const size_t size_before = upb_env_bytesallocated(env);
11951b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#endif
11952b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_json_parser *p = upb_env_malloc(env, sizeof(upb_json_parser));
11953b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!p) return false;
11954b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11955b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  p->env = env;
11956b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  p->method = method;
11957b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  p->limit = p->stack + UPB_JSON_MAX_DEPTH;
11958b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  p->accumulate_buf = NULL;
11959b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  p->accumulate_buf_size = 0;
11960b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_bytessink_reset(&p->input_, &method->input_handler_, p);
11961b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11962b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  json_parser_reset(p);
11963b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_sink_reset(&p->top->sink, output->handlers, output->closure);
11964b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  p->top->m = upb_handlers_msgdef(output->handlers);
11965b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  set_name_table(p, p->top);
11966b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11967b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* If this fails, uncomment and increase the value in parser.h. */
11968b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* fprintf(stderr, "%zd\n", upb_env_bytesallocated(env) - size_before); */
11969b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(upb_env_bytesallocated(env) - size_before <= UPB_JSON_PARSER_SIZE);
11970b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return p;
11971b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
11972b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11973b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerupb_bytessink *upb_json_parser_input(upb_json_parser *p) {
11974b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return &p->input_;
11975b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
11976b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11977b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerupb_json_parsermethod *upb_json_parsermethod_new(const upb_msgdef* md,
11978b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                                 const void* owner) {
11979b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  static const struct upb_refcounted_vtbl vtbl = {visit_json_parsermethod,
11980b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                                  free_json_parsermethod};
11981b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_json_parsermethod *ret = upb_gmalloc(sizeof(*ret));
11982b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_refcounted_init(upb_json_parsermethod_upcast_mutable(ret), &vtbl, owner);
11983b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11984b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  ret->msg = md;
11985b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_ref2(md, ret);
11986b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11987b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_byteshandler_init(&ret->input_handler_);
11988b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_byteshandler_setstring(&ret->input_handler_, parse, ret);
11989b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_byteshandler_setendstr(&ret->input_handler_, end, ret);
11990b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11991b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_inttable_init(&ret->name_tables, UPB_CTYPE_PTR);
11992b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11993b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  add_jsonname_table(ret, md);
11994b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11995b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return ret;
11996b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
11997b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
11998b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_byteshandler *upb_json_parsermethod_inputhandler(
11999b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    const upb_json_parsermethod *m) {
12000b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return &m->input_handler_;
12001b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
12002b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/*
12003b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** This currently uses snprintf() to format primitives, and could be optimized
12004b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer** further.
12005b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer*/
12006b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12007b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12008b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <string.h>
12009b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#include <stdint.h>
12010b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12011b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstruct upb_json_printer {
12012b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_sink input_;
12013b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* BytesSink closure. */
12014b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  void *subc_;
12015b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_bytessink *output_;
12016b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12017b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* We track the depth so that we know when to emit startstr/endstr on the
12018b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * output. */
12019b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  int depth_;
12020b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12021b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Have we emitted the first element? This state is necessary to emit commas
12022b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * without leaving a trailing comma in arrays/maps. We keep this state per
12023b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * frame depth.
12024b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   *
12025b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * Why max_depth * 2? UPB_MAX_HANDLER_DEPTH counts depth as nested messages.
12026b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * We count frames (contexts in which we separate elements by commas) as both
12027b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * repeated fields and messages (maps), and the worst case is a
12028b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * message->repeated field->submessage->repeated field->... nesting. */
12029b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bool first_elem_[UPB_MAX_HANDLER_DEPTH * 2];
12030b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer};
12031b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12032b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* StringPiece; a pointer plus a length. */
12033b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammertypedef struct {
12034b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  char *ptr;
12035b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  size_t len;
12036b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer} strpc;
12037b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12038b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid freestrpc(void *ptr) {
12039b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  strpc *pc = ptr;
12040b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_gfree(pc->ptr);
12041b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_gfree(pc);
12042b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
12043b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12044b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Convert fielddef name to JSON name and return as a string piece. */
12045b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstrpc *newstrpc(upb_handlers *h, const upb_fielddef *f,
12046b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                bool preserve_fieldnames) {
12047b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* TODO(haberman): handle malloc failure. */
12048b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  strpc *ret = upb_gmalloc(sizeof(*ret));
12049b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (preserve_fieldnames) {
12050b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    ret->ptr = upb_gstrdup(upb_fielddef_name(f));
12051b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    ret->len = strlen(ret->ptr);
12052b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
12053b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    size_t len;
12054b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    ret->len = upb_fielddef_getjsonname(f, NULL, 0);
12055b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    ret->ptr = upb_gmalloc(ret->len);
12056b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    len = upb_fielddef_getjsonname(f, ret->ptr, ret->len);
12057b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    UPB_ASSERT_VAR(len, len == ret->len);
12058b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    ret->len--;  /* NULL */
12059b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
12060b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12061b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_handlers_addcleanup(h, ret, freestrpc);
12062b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return ret;
12063b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
12064b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12065b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* ------------ JSON string printing: values, maps, arrays ------------------ */
12066b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12067b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void print_data(
12068b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_json_printer *p, const char *buf, unsigned int len) {
12069b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* TODO: Will need to change if we support pushback from the sink. */
12070b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  size_t n = upb_bytessink_putbuf(p->output_, p->subc_, buf, len, NULL);
12071b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_ASSERT_VAR(n, n == len);
12072b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
12073b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12074b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void print_comma(upb_json_printer *p) {
12075b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!p->first_elem_[p->depth_]) {
12076b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    print_data(p, ",", 1);
12077b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
12078b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  p->first_elem_[p->depth_] = false;
12079b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
12080b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12081b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Helpers that print properly formatted elements to the JSON output stream. */
12082b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12083b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Used for escaping control chars in strings. */
12084b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic const char kControlCharLimit = 0x20;
12085b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12086b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerUPB_INLINE bool is_json_escaped(char c) {
12087b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* See RFC 4627. */
12088b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  unsigned char uc = (unsigned char)c;
12089b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return uc < kControlCharLimit || uc == '"' || uc == '\\';
12090b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
12091b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12092b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerUPB_INLINE const char* json_nice_escape(char c) {
12093b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  switch (c) {
12094b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case '"':  return "\\\"";
12095b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case '\\': return "\\\\";
12096b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case '\b': return "\\b";
12097b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case '\f': return "\\f";
12098b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case '\n': return "\\n";
12099b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case '\r': return "\\r";
12100b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case '\t': return "\\t";
12101b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    default:   return NULL;
12102b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
12103b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
12104b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12105b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Write a properly escaped string chunk. The surrounding quotes are *not*
12106b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * printed; this is so that the caller has the option of emitting the string
12107b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * content in chunks. */
12108b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void putstring(upb_json_printer *p, const char *buf, unsigned int len) {
12109b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const char* unescaped_run = NULL;
12110b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  unsigned int i;
12111b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for (i = 0; i < len; i++) {
12112b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    char c = buf[i];
12113b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* Handle escaping. */
12114b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (is_json_escaped(c)) {
12115b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      /* Use a "nice" escape, like \n, if one exists for this character. */
12116b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      const char* escape = json_nice_escape(c);
12117b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      /* If we don't have a specific 'nice' escape code, use a \uXXXX-style
12118b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer       * escape. */
12119b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      char escape_buf[8];
12120b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (!escape) {
12121b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        unsigned char byte = (unsigned char)c;
12122b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        _upb_snprintf(escape_buf, sizeof(escape_buf), "\\u%04x", (int)byte);
12123b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        escape = escape_buf;
12124b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
12125b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12126b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      /* N.B. that we assume that the input encoding is equal to the output
12127b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer       * encoding (both UTF-8 for  now), so for chars >= 0x20 and != \, ", we
12128b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer       * can simply pass the bytes through. */
12129b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12130b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      /* If there's a current run of unescaped chars, print that run first. */
12131b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (unescaped_run) {
12132b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        print_data(p, unescaped_run, &buf[i] - unescaped_run);
12133b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        unescaped_run = NULL;
12134b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
12135b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      /* Then print the escape code. */
12136b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      print_data(p, escape, strlen(escape));
12137b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    } else {
12138b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      /* Add to the current unescaped run of characters. */
12139b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (unescaped_run == NULL) {
12140b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        unescaped_run = &buf[i];
12141b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
12142b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
12143b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
12144b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12145b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* If the string ended in a run of unescaped characters, print that last run. */
12146b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (unescaped_run) {
12147b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    print_data(p, unescaped_run, &buf[len] - unescaped_run);
12148b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
12149b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
12150b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12151b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#define CHKLENGTH(x) if (!(x)) return -1;
12152b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12153b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Helpers that format floating point values according to our custom formats.
12154b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * Right now we use %.8g and %.17g for float/double, respectively, to match
12155b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * proto2::util::JsonFormat's defaults.  May want to change this later. */
12156b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12157b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic size_t fmt_double(double val, char* buf, size_t length) {
12158b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  size_t n = _upb_snprintf(buf, length, "%.17g", val);
12159b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  CHKLENGTH(n > 0 && n < length);
12160b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return n;
12161b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
12162b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12163b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic size_t fmt_float(float val, char* buf, size_t length) {
12164b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  size_t n = _upb_snprintf(buf, length, "%.8g", val);
12165b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  CHKLENGTH(n > 0 && n < length);
12166b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return n;
12167b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
12168b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12169b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic size_t fmt_bool(bool val, char* buf, size_t length) {
12170b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  size_t n = _upb_snprintf(buf, length, "%s", (val ? "true" : "false"));
12171b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  CHKLENGTH(n > 0 && n < length);
12172b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return n;
12173b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
12174b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12175b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic size_t fmt_int64(long val, char* buf, size_t length) {
12176b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  size_t n = _upb_snprintf(buf, length, "%ld", val);
12177b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  CHKLENGTH(n > 0 && n < length);
12178b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return n;
12179b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
12180b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12181b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic size_t fmt_uint64(unsigned long long val, char* buf, size_t length) {
12182b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  size_t n = _upb_snprintf(buf, length, "%llu", val);
12183b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  CHKLENGTH(n > 0 && n < length);
12184b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return n;
12185b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
12186b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12187b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Print a map key given a field name. Called by scalar field handlers and by
12188b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * startseq for repeated fields. */
12189b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool putkey(void *closure, const void *handler_data) {
12190b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_json_printer *p = closure;
12191b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const strpc *key = handler_data;
12192b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  print_comma(p);
12193b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  print_data(p, "\"", 1);
12194b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  putstring(p, key->ptr, key->len);
12195b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  print_data(p, "\":", 2);
12196b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
12197b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
12198b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12199b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#define CHKFMT(val) if ((val) == (size_t)-1) return false;
12200b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#define CHK(val)    if (!(val)) return false;
12201b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12202b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#define TYPE_HANDLERS(type, fmt_func)                                        \
12203b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  static bool put##type(void *closure, const void *handler_data, type val) { \
12204b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_json_printer *p = closure;                                           \
12205b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    char data[64];                                                           \
12206b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    size_t length = fmt_func(val, data, sizeof(data));                       \
12207b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    UPB_UNUSED(handler_data);                                                \
12208b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    CHKFMT(length);                                                          \
12209b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    print_data(p, data, length);                                             \
12210b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return true;                                                             \
12211b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }                                                                          \
12212b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  static bool scalar_##type(void *closure, const void *handler_data,         \
12213b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                            type val) {                                      \
12214b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    CHK(putkey(closure, handler_data));                                      \
12215b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    CHK(put##type(closure, handler_data, val));                              \
12216b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return true;                                                             \
12217b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }                                                                          \
12218b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  static bool repeated_##type(void *closure, const void *handler_data,       \
12219b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                              type val) {                                    \
12220b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_json_printer *p = closure;                                           \
12221b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    print_comma(p);                                                          \
12222b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    CHK(put##type(closure, handler_data, val));                              \
12223b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return true;                                                             \
12224b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
12225b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12226b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#define TYPE_HANDLERS_MAPKEY(type, fmt_func)                                 \
12227b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  static bool putmapkey_##type(void *closure, const void *handler_data,      \
12228b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                            type val) {                                      \
12229b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_json_printer *p = closure;                                           \
12230b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    print_data(p, "\"", 1);                                                  \
12231b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    CHK(put##type(closure, handler_data, val));                              \
12232b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    print_data(p, "\":", 2);                                                 \
12233b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return true;                                                             \
12234b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
12235b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12236b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerTYPE_HANDLERS(double,   fmt_double)
12237b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerTYPE_HANDLERS(float,    fmt_float)
12238b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerTYPE_HANDLERS(bool,     fmt_bool)
12239b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerTYPE_HANDLERS(int32_t,  fmt_int64)
12240b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerTYPE_HANDLERS(uint32_t, fmt_int64)
12241b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerTYPE_HANDLERS(int64_t,  fmt_int64)
12242b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerTYPE_HANDLERS(uint64_t, fmt_uint64)
12243b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12244b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* double and float are not allowed to be map keys. */
12245b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerTYPE_HANDLERS_MAPKEY(bool,     fmt_bool)
12246b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerTYPE_HANDLERS_MAPKEY(int32_t,  fmt_int64)
12247b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerTYPE_HANDLERS_MAPKEY(uint32_t, fmt_int64)
12248b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerTYPE_HANDLERS_MAPKEY(int64_t,  fmt_int64)
12249b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas BerghammerTYPE_HANDLERS_MAPKEY(uint64_t, fmt_uint64)
12250b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12251b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#undef TYPE_HANDLERS
12252b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#undef TYPE_HANDLERS_MAPKEY
12253b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12254b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammertypedef struct {
12255b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  void *keyname;
12256b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const upb_enumdef *enumdef;
12257b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer} EnumHandlerData;
12258b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12259b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool scalar_enum(void *closure, const void *handler_data,
12260b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                        int32_t val) {
12261b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const EnumHandlerData *hd = handler_data;
12262b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_json_printer *p = closure;
12263b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const char *symbolic_name;
12264b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12265b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  CHK(putkey(closure, hd->keyname));
12266b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12267b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  symbolic_name = upb_enumdef_iton(hd->enumdef, val);
12268b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (symbolic_name) {
12269b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    print_data(p, "\"", 1);
12270b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putstring(p, symbolic_name, strlen(symbolic_name));
12271b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    print_data(p, "\"", 1);
12272b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
12273b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putint32_t(closure, NULL, val);
12274b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
12275b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12276b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
12277b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
12278b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12279b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void print_enum_symbolic_name(upb_json_printer *p,
12280b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                     const upb_enumdef *def,
12281b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                     int32_t val) {
12282b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const char *symbolic_name = upb_enumdef_iton(def, val);
12283b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (symbolic_name) {
12284b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    print_data(p, "\"", 1);
12285b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putstring(p, symbolic_name, strlen(symbolic_name));
12286b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    print_data(p, "\"", 1);
12287b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  } else {
12288b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    putint32_t(p, NULL, val);
12289b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
12290b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
12291b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12292b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool repeated_enum(void *closure, const void *handler_data,
12293b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                          int32_t val) {
12294b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const EnumHandlerData *hd = handler_data;
12295b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_json_printer *p = closure;
12296b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  print_comma(p);
12297b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12298b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  print_enum_symbolic_name(p, hd->enumdef, val);
12299b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12300b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
12301b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
12302b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12303b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool mapvalue_enum(void *closure, const void *handler_data,
12304b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                          int32_t val) {
12305b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const EnumHandlerData *hd = handler_data;
12306b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_json_printer *p = closure;
12307b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12308b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  print_enum_symbolic_name(p, hd->enumdef, val);
12309b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12310b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
12311b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
12312b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12313b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void *scalar_startsubmsg(void *closure, const void *handler_data) {
12314b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return putkey(closure, handler_data) ? closure : UPB_BREAK;
12315b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
12316b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12317b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void *repeated_startsubmsg(void *closure, const void *handler_data) {
12318b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_json_printer *p = closure;
12319b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(handler_data);
12320b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  print_comma(p);
12321b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return closure;
12322b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
12323b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12324b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void start_frame(upb_json_printer *p) {
12325b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  p->depth_++;
12326b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  p->first_elem_[p->depth_] = true;
12327b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  print_data(p, "{", 1);
12328b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
12329b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12330b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void end_frame(upb_json_printer *p) {
12331b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  print_data(p, "}", 1);
12332b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  p->depth_--;
12333b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
12334b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12335b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool printer_startmsg(void *closure, const void *handler_data) {
12336b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_json_printer *p = closure;
12337b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(handler_data);
12338b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (p->depth_ == 0) {
12339b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_bytessink_start(p->output_, 0, &p->subc_);
12340b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
12341b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  start_frame(p);
12342b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
12343b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
12344b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12345b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool printer_endmsg(void *closure, const void *handler_data, upb_status *s) {
12346b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_json_printer *p = closure;
12347b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(handler_data);
12348b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(s);
12349b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  end_frame(p);
12350b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (p->depth_ == 0) {
12351b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_bytessink_end(p->output_);
12352b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
12353b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
12354b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
12355b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12356b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void *startseq(void *closure, const void *handler_data) {
12357b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_json_printer *p = closure;
12358b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  CHK(putkey(closure, handler_data));
12359b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  p->depth_++;
12360b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  p->first_elem_[p->depth_] = true;
12361b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  print_data(p, "[", 1);
12362b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return closure;
12363b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
12364b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12365b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool endseq(void *closure, const void *handler_data) {
12366b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_json_printer *p = closure;
12367b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(handler_data);
12368b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  print_data(p, "]", 1);
12369b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  p->depth_--;
12370b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
12371b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
12372b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12373b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void *startmap(void *closure, const void *handler_data) {
12374b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_json_printer *p = closure;
12375b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  CHK(putkey(closure, handler_data));
12376b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  p->depth_++;
12377b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  p->first_elem_[p->depth_] = true;
12378b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  print_data(p, "{", 1);
12379b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return closure;
12380b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
12381b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12382b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool endmap(void *closure, const void *handler_data) {
12383b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_json_printer *p = closure;
12384b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(handler_data);
12385b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  print_data(p, "}", 1);
12386b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  p->depth_--;
12387b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
12388b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
12389b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12390b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic size_t putstr(void *closure, const void *handler_data, const char *str,
12391b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                     size_t len, const upb_bufhandle *handle) {
12392b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_json_printer *p = closure;
12393b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(handler_data);
12394b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(handle);
12395b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  putstring(p, str, len);
12396b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return len;
12397b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
12398b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12399b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* This has to Base64 encode the bytes, because JSON has no "bytes" type. */
12400b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic size_t putbytes(void *closure, const void *handler_data, const char *str,
12401b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                       size_t len, const upb_bufhandle *handle) {
12402b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_json_printer *p = closure;
12403b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12404b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* This is the regular base64, not the "web-safe" version. */
12405b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  static const char base64[] =
12406b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
12407b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12408b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* Base64-encode. */
12409b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  char data[16000];
12410b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const char *limit = data + sizeof(data);
12411b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const unsigned char *from = (const unsigned char*)str;
12412b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  char *to = data;
12413b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  size_t remaining = len;
12414b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  size_t bytes;
12415b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12416b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(handler_data);
12417b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(handle);
12418b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12419b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  while (remaining > 2) {
12420b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* TODO(haberman): handle encoded lengths > sizeof(data) */
12421b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    UPB_ASSERT_VAR(limit, (limit - to) >= 4);
12422b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12423b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    to[0] = base64[from[0] >> 2];
12424b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    to[1] = base64[((from[0] & 0x3) << 4) | (from[1] >> 4)];
12425b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    to[2] = base64[((from[1] & 0xf) << 2) | (from[2] >> 6)];
12426b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    to[3] = base64[from[2] & 0x3f];
12427b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12428b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    remaining -= 3;
12429b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    to += 4;
12430b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    from += 3;
12431b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
12432b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12433b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  switch (remaining) {
12434b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case 2:
12435b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      to[0] = base64[from[0] >> 2];
12436b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      to[1] = base64[((from[0] & 0x3) << 4) | (from[1] >> 4)];
12437b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      to[2] = base64[(from[1] & 0xf) << 2];
12438b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      to[3] = '=';
12439b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      to += 4;
12440b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      from += 2;
12441b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
12442b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case 1:
12443b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      to[0] = base64[from[0] >> 2];
12444b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      to[1] = base64[((from[0] & 0x3) << 4)];
12445b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      to[2] = '=';
12446b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      to[3] = '=';
12447b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      to += 4;
12448b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      from += 1;
12449b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
12450b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
12451b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12452b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bytes = to - data;
12453b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  print_data(p, "\"", 1);
12454b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  putstring(p, data, bytes);
12455b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  print_data(p, "\"", 1);
12456b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return len;
12457b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
12458b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12459b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void *scalar_startstr(void *closure, const void *handler_data,
12460b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                             size_t size_hint) {
12461b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_json_printer *p = closure;
12462b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(handler_data);
12463b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(size_hint);
12464b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  CHK(putkey(closure, handler_data));
12465b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  print_data(p, "\"", 1);
12466b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return p;
12467b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
12468b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12469b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic size_t scalar_str(void *closure, const void *handler_data,
12470b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                         const char *str, size_t len,
12471b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                         const upb_bufhandle *handle) {
12472b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  CHK(putstr(closure, handler_data, str, len, handle));
12473b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return len;
12474b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
12475b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12476b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool scalar_endstr(void *closure, const void *handler_data) {
12477b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_json_printer *p = closure;
12478b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(handler_data);
12479b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  print_data(p, "\"", 1);
12480b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
12481b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
12482b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12483b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void *repeated_startstr(void *closure, const void *handler_data,
12484b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                               size_t size_hint) {
12485b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_json_printer *p = closure;
12486b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(handler_data);
12487b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(size_hint);
12488b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  print_comma(p);
12489b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  print_data(p, "\"", 1);
12490b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return p;
12491b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
12492b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12493b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic size_t repeated_str(void *closure, const void *handler_data,
12494b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                           const char *str, size_t len,
12495b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                           const upb_bufhandle *handle) {
12496b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  CHK(putstr(closure, handler_data, str, len, handle));
12497b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return len;
12498b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
12499b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12500b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool repeated_endstr(void *closure, const void *handler_data) {
12501b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_json_printer *p = closure;
12502b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(handler_data);
12503b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  print_data(p, "\"", 1);
12504b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
12505b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
12506b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12507b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void *mapkeyval_startstr(void *closure, const void *handler_data,
12508b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                size_t size_hint) {
12509b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_json_printer *p = closure;
12510b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(handler_data);
12511b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(size_hint);
12512b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  print_data(p, "\"", 1);
12513b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return p;
12514b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
12515b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12516b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic size_t mapkey_str(void *closure, const void *handler_data,
12517b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                         const char *str, size_t len,
12518b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                         const upb_bufhandle *handle) {
12519b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  CHK(putstr(closure, handler_data, str, len, handle));
12520b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return len;
12521b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
12522b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12523b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool mapkey_endstr(void *closure, const void *handler_data) {
12524b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_json_printer *p = closure;
12525b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(handler_data);
12526b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  print_data(p, "\":", 2);
12527b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
12528b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
12529b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12530b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic bool mapvalue_endstr(void *closure, const void *handler_data) {
12531b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_json_printer *p = closure;
12532b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(handler_data);
12533b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  print_data(p, "\"", 1);
12534b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return true;
12535b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
12536b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12537b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic size_t scalar_bytes(void *closure, const void *handler_data,
12538b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                           const char *str, size_t len,
12539b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                           const upb_bufhandle *handle) {
12540b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  CHK(putkey(closure, handler_data));
12541b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  CHK(putbytes(closure, handler_data, str, len, handle));
12542b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return len;
12543b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
12544b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12545b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic size_t repeated_bytes(void *closure, const void *handler_data,
12546b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                             const char *str, size_t len,
12547b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                             const upb_bufhandle *handle) {
12548b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_json_printer *p = closure;
12549b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  print_comma(p);
12550b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  CHK(putbytes(closure, handler_data, str, len, handle));
12551b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return len;
12552b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
12553b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12554b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic size_t mapkey_bytes(void *closure, const void *handler_data,
12555b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                           const char *str, size_t len,
12556b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                           const upb_bufhandle *handle) {
12557b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_json_printer *p = closure;
12558b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  CHK(putbytes(closure, handler_data, str, len, handle));
12559b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  print_data(p, ":", 1);
12560b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return len;
12561b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
12562b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12563b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void set_enum_hd(upb_handlers *h,
12564b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                        const upb_fielddef *f,
12565b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                        bool preserve_fieldnames,
12566b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                        upb_handlerattr *attr) {
12567b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  EnumHandlerData *hd = upb_gmalloc(sizeof(EnumHandlerData));
12568b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  hd->enumdef = (const upb_enumdef *)upb_fielddef_subdef(f);
12569b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  hd->keyname = newstrpc(h, f, preserve_fieldnames);
12570b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_handlers_addcleanup(h, hd, upb_gfree);
12571b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_handlerattr_sethandlerdata(attr, hd);
12572b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
12573b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12574b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Set up handlers for a mapentry submessage (i.e., an individual key/value pair
12575b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * in a map).
12576b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer *
12577b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * TODO: Handle missing key, missing value, out-of-order key/value, or repeated
12578b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * key or value cases properly. The right way to do this is to allocate a
12579b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * temporary structure at the start of a mapentry submessage, store key and
12580b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * value data in it as key and value handlers are called, and then print the
12581b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * key/value pair once at the end of the submessage. If we don't do this, we
12582b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * should at least detect the case and throw an error. However, so far all of
12583b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * our sources that emit mapentry messages do so canonically (with one key
12584b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * field, and then one value field), so this is not a pressing concern at the
12585b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer * moment. */
12586b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid printer_sethandlers_mapentry(const void *closure, bool preserve_fieldnames,
12587b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                  upb_handlers *h) {
12588b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const upb_msgdef *md = upb_handlers_msgdef(h);
12589b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12590b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* A mapentry message is printed simply as '"key": value'. Rather than
12591b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * special-case key and value for every type below, we just handle both
12592b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * fields explicitly here. */
12593b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const upb_fielddef* key_field = upb_msgdef_itof(md, UPB_MAPENTRY_KEY);
12594b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const upb_fielddef* value_field = upb_msgdef_itof(md, UPB_MAPENTRY_VALUE);
12595b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12596b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_handlerattr empty_attr = UPB_HANDLERATTR_INITIALIZER;
12597b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12598b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  UPB_UNUSED(closure);
12599b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12600b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  switch (upb_fielddef_type(key_field)) {
12601b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_INT32:
12602b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_handlers_setint32(h, key_field, putmapkey_int32_t, &empty_attr);
12603b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
12604b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_INT64:
12605b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_handlers_setint64(h, key_field, putmapkey_int64_t, &empty_attr);
12606b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
12607b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_UINT32:
12608b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_handlers_setuint32(h, key_field, putmapkey_uint32_t, &empty_attr);
12609b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
12610b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_UINT64:
12611b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_handlers_setuint64(h, key_field, putmapkey_uint64_t, &empty_attr);
12612b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
12613b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_BOOL:
12614b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_handlers_setbool(h, key_field, putmapkey_bool, &empty_attr);
12615b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
12616b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_STRING:
12617b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_handlers_setstartstr(h, key_field, mapkeyval_startstr, &empty_attr);
12618b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_handlers_setstring(h, key_field, mapkey_str, &empty_attr);
12619b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_handlers_setendstr(h, key_field, mapkey_endstr, &empty_attr);
12620b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
12621b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_BYTES:
12622b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_handlers_setstring(h, key_field, mapkey_bytes, &empty_attr);
12623b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
12624b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    default:
12625b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      assert(false);
12626b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
12627b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
12628b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12629b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  switch (upb_fielddef_type(value_field)) {
12630b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_INT32:
12631b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_handlers_setint32(h, value_field, putint32_t, &empty_attr);
12632b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
12633b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_INT64:
12634b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_handlers_setint64(h, value_field, putint64_t, &empty_attr);
12635b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
12636b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_UINT32:
12637b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_handlers_setuint32(h, value_field, putuint32_t, &empty_attr);
12638b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
12639b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_UINT64:
12640b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_handlers_setuint64(h, value_field, putuint64_t, &empty_attr);
12641b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
12642b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_BOOL:
12643b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_handlers_setbool(h, value_field, putbool, &empty_attr);
12644b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
12645b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_FLOAT:
12646b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_handlers_setfloat(h, value_field, putfloat, &empty_attr);
12647b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
12648b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_DOUBLE:
12649b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_handlers_setdouble(h, value_field, putdouble, &empty_attr);
12650b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
12651b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_STRING:
12652b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_handlers_setstartstr(h, value_field, mapkeyval_startstr, &empty_attr);
12653b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_handlers_setstring(h, value_field, putstr, &empty_attr);
12654b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_handlers_setendstr(h, value_field, mapvalue_endstr, &empty_attr);
12655b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
12656b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_BYTES:
12657b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_handlers_setstring(h, value_field, putbytes, &empty_attr);
12658b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
12659b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_ENUM: {
12660b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_handlerattr enum_attr = UPB_HANDLERATTR_INITIALIZER;
12661b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      set_enum_hd(h, value_field, preserve_fieldnames, &enum_attr);
12662b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_handlers_setint32(h, value_field, mapvalue_enum, &enum_attr);
12663b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_handlerattr_uninit(&enum_attr);
12664b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
12665b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
12666b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    case UPB_TYPE_MESSAGE:
12667b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      /* No handler necessary -- the submsg handlers will print the message
12668b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer       * as appropriate. */
12669b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      break;
12670b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
12671b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12672b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_handlerattr_uninit(&empty_attr);
12673b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
12674b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12675b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammervoid printer_sethandlers(const void *closure, upb_handlers *h) {
12676b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const upb_msgdef *md = upb_handlers_msgdef(h);
12677b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  bool is_mapentry = upb_msgdef_mapentry(md);
12678b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_handlerattr empty_attr = UPB_HANDLERATTR_INITIALIZER;
12679b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_msg_field_iter i;
12680b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const bool *preserve_fieldnames_ptr = closure;
12681b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  const bool preserve_fieldnames = *preserve_fieldnames_ptr;
12682b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12683b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (is_mapentry) {
12684b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /* mapentry messages are sufficiently different that we handle them
12685b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * separately. */
12686b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    printer_sethandlers_mapentry(closure, preserve_fieldnames, h);
12687b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return;
12688b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
12689b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12690b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_handlers_setstartmsg(h, printer_startmsg, &empty_attr);
12691b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_handlers_setendmsg(h, printer_endmsg, &empty_attr);
12692b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12693b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#define TYPE(type, name, ctype)                                               \
12694b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  case type:                                                                  \
12695b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (upb_fielddef_isseq(f)) {                                              \
12696b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_handlers_set##name(h, f, repeated_##ctype, &empty_attr);            \
12697b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    } else {                                                                  \
12698b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_handlers_set##name(h, f, scalar_##ctype, &name_attr);               \
12699b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }                                                                         \
12700b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    break;
12701b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12702b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_msg_field_begin(&i, md);
12703b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  for(; !upb_msg_field_done(&i); upb_msg_field_next(&i)) {
12704b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    const upb_fielddef *f = upb_msg_iter_field(&i);
12705b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12706b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_handlerattr name_attr = UPB_HANDLERATTR_INITIALIZER;
12707b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_handlerattr_sethandlerdata(&name_attr,
12708b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                   newstrpc(h, f, preserve_fieldnames));
12709b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12710b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (upb_fielddef_ismap(f)) {
12711b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_handlers_setstartseq(h, f, startmap, &name_attr);
12712b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_handlers_setendseq(h, f, endmap, &name_attr);
12713b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    } else if (upb_fielddef_isseq(f)) {
12714b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_handlers_setstartseq(h, f, startseq, &name_attr);
12715b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      upb_handlers_setendseq(h, f, endseq, &empty_attr);
12716b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
12717b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12718b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    switch (upb_fielddef_type(f)) {
12719b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      TYPE(UPB_TYPE_FLOAT,  float,  float);
12720b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      TYPE(UPB_TYPE_DOUBLE, double, double);
12721b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      TYPE(UPB_TYPE_BOOL,   bool,   bool);
12722b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      TYPE(UPB_TYPE_INT32,  int32,  int32_t);
12723b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      TYPE(UPB_TYPE_UINT32, uint32, uint32_t);
12724b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      TYPE(UPB_TYPE_INT64,  int64,  int64_t);
12725b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      TYPE(UPB_TYPE_UINT64, uint64, uint64_t);
12726b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case UPB_TYPE_ENUM: {
12727b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        /* For now, we always emit symbolic names for enums. We may want an
12728b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer         * option later to control this behavior, but we will wait for a real
12729b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer         * need first. */
12730b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_handlerattr enum_attr = UPB_HANDLERATTR_INITIALIZER;
12731b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        set_enum_hd(h, f, preserve_fieldnames, &enum_attr);
12732b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12733b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        if (upb_fielddef_isseq(f)) {
12734b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          upb_handlers_setint32(h, f, repeated_enum, &enum_attr);
12735b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        } else {
12736b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          upb_handlers_setint32(h, f, scalar_enum, &enum_attr);
12737b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        }
12738b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12739b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        upb_handlerattr_uninit(&enum_attr);
12740b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        break;
12741b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
12742b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case UPB_TYPE_STRING:
12743b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        if (upb_fielddef_isseq(f)) {
12744b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          upb_handlers_setstartstr(h, f, repeated_startstr, &empty_attr);
12745b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          upb_handlers_setstring(h, f, repeated_str, &empty_attr);
12746b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          upb_handlers_setendstr(h, f, repeated_endstr, &empty_attr);
12747b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        } else {
12748b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          upb_handlers_setstartstr(h, f, scalar_startstr, &name_attr);
12749b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          upb_handlers_setstring(h, f, scalar_str, &empty_attr);
12750b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          upb_handlers_setendstr(h, f, scalar_endstr, &empty_attr);
12751b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        }
12752b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        break;
12753b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case UPB_TYPE_BYTES:
12754b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        /* XXX: this doesn't support strings that span buffers yet. The base64
12755b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer         * encoder will need to be made resumable for this to work properly. */
12756b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        if (upb_fielddef_isseq(f)) {
12757b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          upb_handlers_setstring(h, f, repeated_bytes, &empty_attr);
12758b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        } else {
12759b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          upb_handlers_setstring(h, f, scalar_bytes, &name_attr);
12760b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        }
12761b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        break;
12762b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      case UPB_TYPE_MESSAGE:
12763b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        if (upb_fielddef_isseq(f)) {
12764b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          upb_handlers_setstartsubmsg(h, f, repeated_startsubmsg, &name_attr);
12765b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        } else {
12766b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          upb_handlers_setstartsubmsg(h, f, scalar_startsubmsg, &name_attr);
12767b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        }
12768b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        break;
12769b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
12770b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12771b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    upb_handlerattr_uninit(&name_attr);
12772b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
12773b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12774b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_handlerattr_uninit(&empty_attr);
12775b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#undef TYPE
12776b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
12777b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12778b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerstatic void json_printer_reset(upb_json_printer *p) {
12779b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  p->depth_ = 0;
12780b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
12781b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12782b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12783b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer/* Public API *****************************************************************/
12784b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12785b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerupb_json_printer *upb_json_printer_create(upb_env *e, const upb_handlers *h,
12786b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                          upb_bytessink *output) {
12787b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#ifndef NDEBUG
12788b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  size_t size_before = upb_env_bytesallocated(e);
12789b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer#endif
12790b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12791b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_json_printer *p = upb_env_malloc(e, sizeof(upb_json_printer));
12792b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  if (!p) return NULL;
12793b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12794b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  p->output_ = output;
12795b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  json_printer_reset(p);
12796b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  upb_sink_reset(&p->input_, h, p);
12797b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12798b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /* If this fails, increase the value in printer.h. */
12799b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  assert(upb_env_bytesallocated(e) - size_before <= UPB_JSON_PRINTER_SIZE);
12800b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return p;
12801b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
12802b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12803b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerupb_sink *upb_json_printer_input(upb_json_printer *p) {
12804b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return &p->input_;
12805b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
12806b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
12807b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerconst upb_handlers *upb_json_printer_newhandlers(const upb_msgdef *md,
12808b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                                 bool preserve_fieldnames,
12809b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                                                 const void *owner) {
12810b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  return upb_handlers_newfrozen(
12811b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      md, owner, printer_sethandlers, &preserve_fieldnames);
12812b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer}
12813