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