upb_def *upb_def_dup(const upb_def *def) { switch (def->type) { case UPB_DEF_MSG: return UPB_UPCAST(upb_msgdef_dup(upb_downcast_msgdef_const(def))); case UPB_DEF_ENUM: return UPB_UPCAST(upb_enumdef_dup(upb_downcast_enumdef_const(def))); default: assert(false); return NULL; } }
upb_def *upb_def_dup(const upb_def *def, const void *o) { switch (def->type) { case UPB_DEF_MSG: return UPB_UPCAST(upb_msgdef_dup(upb_downcast_msgdef(def), o)); case UPB_DEF_FIELD: return UPB_UPCAST(upb_fielddef_dup(upb_downcast_fielddef(def), o)); case UPB_DEF_ENUM: return UPB_UPCAST(upb_enumdef_dup(upb_downcast_enumdef(def), o)); default: assert(false); return NULL; } }
upb_fielddef *upb_fielddef_new(const void *owner) { static const struct upb_refcounted_vtbl vtbl = {visitfield, freefield}; upb_fielddef *f = malloc(sizeof(*f)); if (!f) return NULL; if (!upb_def_init(UPB_UPCAST(f), UPB_DEF_FIELD, &vtbl, owner)) { free(f); return NULL; } f->msg.def = NULL; f->sub.def = NULL; f->subdef_is_symbolic = false; f->msg_is_symbolic = false; f->label_ = UPB_LABEL_OPTIONAL; f->type_ = UPB_TYPE_INT32; f->number_ = 0; f->type_is_set_ = false; f->tagdelim = false; f->is_extension_ = false; f->lazy_ = false; // For the moment we default this to UPB_INTFMT_VARIABLE, since it will work // with all integer types and is in some since more "default" since the most // normal-looking proto2 types int32/int64/uint32/uint64 use variable. // // Other options to consider: // - there is no default; users must set this manually (like type). // - default signed integers to UPB_INTFMT_ZIGZAG, since it's more likely to // be an optimal default for signed integers. f->intfmt = UPB_INTFMT_VARIABLE; return f; }
// Handlers for google.protobuf.DescriptorProto (representing a message). static bool msg_startmsg(void *closure, const void *hd) { UPB_UNUSED(hd); upb_descreader *r = closure; upb_deflist_push(&r->defs, UPB_UPCAST(upb_msgdef_new(&r->defs))); upb_descreader_startcontainer(r); return true; }
upb_msgdef *upb_msgdef_dup(const upb_msgdef *m, const void *owner) { upb_msgdef *newm = upb_msgdef_new(owner); if (!newm) return NULL; bool ok = upb_def_setfullname(UPB_UPCAST(newm), upb_def_fullname(UPB_UPCAST(m)), NULL); UPB_ASSERT_VAR(ok, ok); upb_msg_iter i; for(upb_msg_begin(&i, m); !upb_msg_done(&i); upb_msg_next(&i)) { upb_fielddef *f = upb_fielddef_dup(upb_msg_iter_field(&i), &f); if (!f || !upb_msgdef_addfield(newm, f, &f, NULL)) { upb_msgdef_unref(newm, owner); return NULL; } } return newm; }
static void freemsg(upb_refcounted *r) { upb_msgdef *m = (upb_msgdef*)r; upb_strtable_uninit(&m->ntof); upb_inttable_uninit(&m->itof); upb_def_uninit(UPB_UPCAST(m)); free(m); }
static void freefield(upb_refcounted *r) { upb_fielddef *f = (upb_fielddef*)r; upb_fielddef_uninit_default(f); if (f->subdef_is_symbolic) free(f->sub.name); upb_def_uninit(UPB_UPCAST(f)); free(f); }
static int PyUpb_MessageDef_setattro( PyObject *o, PyObject *key, PyObject *val) { upb_msgdef *m = Check_MessageDef(o, -1); if (!upb_def_ismutable(UPB_UPCAST(m))) { PyErr_SetString(PyExc_TypeError, "MessageDef is not mutable."); return -1; } const char *name = PyString_AsString(key); if (streql(name, "fqname")) { const char *fqname = PyString_AsString(val); if (!fqname || !upb_def_setfqname(UPB_UPCAST(m), fqname)) return PyUpb_ErrorInt("Invalid fqname"); } else { return PyUpb_ErrorInt("Invalid MessageDef member."); } return 0; }
static void cleanup() { for (int i = 0; i < NUM_MESSAGES; i++) upb_stdmsg_free(msg[i], def); upb_def_unref(UPB_UPCAST(def)); upb_stringsrc_uninit(&strsrc); upb_decoder_uninit(&d); }
static void cleanup() { free(input_str); upb_def_unref(UPB_UPCAST(def), &def); upb_decoder_uninit(&decoder); upb_decoderplan_unref(plan); upb_stringsrc_uninit(&stringsrc); }
mgroup *newgroup(const void *owner) { mgroup *g = malloc(sizeof(*g)); static const struct upb_refcounted_vtbl vtbl = {visitgroup, freegroup}; upb_refcounted_init(UPB_UPCAST(g), &vtbl, owner); upb_inttable_init(&g->methods, UPB_CTYPE_PTR); g->bytecode = NULL; g->bytecode_end = NULL; return g; }
static bool upb_def_init(upb_def *def, upb_deftype_t type, const struct upb_refcounted_vtbl *vtbl, const void *owner) { if (!upb_refcounted_init(UPB_UPCAST(def), vtbl, owner)) return false; def->type = type; def->fullname = NULL; def->came_from_user = false; return true; }
static PyObject *PyUpb_MessageDef_getattro(PyObject *obj, PyObject *attr_name) { upb_msgdef *m = Check_MessageDef(obj, NULL); const char *name = PyString_AsString(attr_name); if (streql(name, "fqname")) { const char *fqname = upb_def_fqname(UPB_UPCAST(m)); return fqname == NULL ? Py_None : PyString_FromString(fqname); } return PyObject_GenericGetAttr(obj, attr_name); }
static bool pushextension(void *closure, const void *hd) { UPB_UNUSED(hd); upb_descreader *r = closure; assert(upb_fielddef_containingtypename(r->f)); upb_fielddef_setisextension(r->f, true); upb_deflist_push(&r->defs, UPB_UPCAST(r->f)); r->f = NULL; return true; }
static void visitfield(const upb_refcounted *r, upb_refcounted_visit *visit, void *closure) { const upb_fielddef *f = (const upb_fielddef*)r; if (upb_fielddef_containingtype(f)) { visit(r, UPB_UPCAST2(upb_fielddef_containingtype(f)), closure); } if (upb_fielddef_subdef(f)) { visit(r, UPB_UPCAST(upb_fielddef_subdef(f)), closure); } }
static void visitgroup(const upb_refcounted *r, upb_refcounted_visit *visit, void *closure) { const mgroup *g = (const mgroup*)r; upb_inttable_iter i; upb_inttable_begin(&i, &g->methods); for(; !upb_inttable_done(&i); upb_inttable_next(&i)) { upb_pbdecodermethod *method = upb_value_getptr(upb_inttable_iter_value(&i)); visit(r, UPB_UPCAST(method), closure); } }
static bool msg_endmsg(void *closure, const void *hd, upb_status *status) { UPB_UNUSED(hd); upb_descreader *r = closure; upb_msgdef *m = upb_descreader_top(r); if(!upb_def_fullname(UPB_UPCAST(m))) { upb_status_seterrmsg(status, "Encountered message with no name."); return false; } upb_descreader_endcontainer(r); return true; }
const upb_msgdef *upb_symtab_lookupmsg(const upb_symtab *s, const char *sym) { upb_rwlock_rdlock(&s->lock); upb_symtab_ent *e = upb_strtable_lookup(&s->symtab, sym); upb_msgdef *ret = NULL; if(e && e->def->type == UPB_DEF_MSG) { ret = upb_downcast_msgdef(e->def); upb_def_ref(UPB_UPCAST(ret)); } upb_rwlock_unlock(&s->lock); return ret; }
static void visithandlers(const upb_refcounted *r, upb_refcounted_visit *visit, void *closure) { const upb_handlers *h = (const upb_handlers*)r; upb_msg_iter i; for(upb_msg_begin(&i, h->msg); !upb_msg_done(&i); upb_msg_next(&i)) { upb_fielddef *f = upb_msg_iter_field(&i); if (!upb_fielddef_issubmsg(f)) continue; const upb_handlers *sub = upb_handlers_getsubhandlers(h, f); if (sub) visit(r, UPB_UPCAST(sub), closure); } }
bool upb_msgdef_setextrange(upb_msgdef *m, uint32_t start, uint32_t end) { assert(upb_def_ismutable(UPB_UPCAST(m))); if (start == 0 && end == 0) { // Clearing the extension range -- ok to fall through. } else if (start >= end || start < 1 || end > UPB_MAX_FIELDNUMBER) { return false; } m->extstart = start; m->extend = start; return true; }
upb_handlers *upb_handlers_new(const upb_msgdef *md, const void *owner) { assert(upb_msgdef_isfrozen(md)); int extra = sizeof(upb_handlers_tabent) * (md->selector_count - 1); upb_handlers *h = calloc(sizeof(*h) + extra, 1); if (!h) return NULL; h->msg = md; upb_msgdef_ref(h->msg, h); upb_status_clear(&h->status_); h->sub = calloc(md->submsg_field_count, sizeof(*h->sub)); if (!h->sub) goto oom; if (!upb_refcounted_init(UPB_UPCAST(h), &vtbl, owner)) goto oom; // calloc() above initialized all handlers to NULL. return h; oom: freehandlers(UPB_UPCAST(h)); return NULL; }
static void cleanup() { if (!BYREF) { // Undo our fabrication from before. input_str->refcount.v = 1; } upb_string_unref(input_str); upb_msg_unref(msg, def); upb_def_unref(UPB_UPCAST(def)); upb_stringsrc_uninit(&strsrc); upb_decoder_uninit(&d); }
static size_t msg_onname(void *closure, const void *hd, const char *buf, size_t n, const upb_bufhandle *handle) { UPB_UNUSED(hd); UPB_UNUSED(handle); upb_descreader *r = closure; upb_msgdef *m = upb_descreader_top(r); // XXX: see comment at the top of the file. char *name = upb_strndup(buf, n); upb_def_setfullname(UPB_UPCAST(m), name, NULL); upb_descreader_setscopename(r, name); // Passes ownership of name. return n; }
static void upb_enumdef_free(upb_refcounted *r) { upb_enumdef *e = (upb_enumdef*)r; upb_inttable_iter i; upb_inttable_begin(&i, &e->iton); for( ; !upb_inttable_done(&i); upb_inttable_next(&i)) { // To clean up the upb_strdup() from upb_enumdef_addval(). free(upb_value_getcstr(upb_inttable_iter_value(&i))); } upb_strtable_uninit(&e->ntoi); upb_inttable_uninit(&e->iton); upb_def_uninit(UPB_UPCAST(e)); free(e); }
bool upb_handlers_setsubhandlers(upb_handlers *h, const upb_fielddef *f, const upb_handlers *sub) { assert(sub); assert(!upb_handlers_isfrozen(h)); assert(upb_fielddef_issubmsg(f)); if (SUBH_F(h, f)) return false; // Can't reset. if (UPB_UPCAST(upb_handlers_msgdef(sub)) != upb_fielddef_subdef(f)) { return false; } SUBH_F(h, f) = sub; upb_ref2(sub, h); return true; }
static upb_pbdecodermethod *newmethod(const upb_handlers *dest_handlers, mgroup *group) { static const struct upb_refcounted_vtbl vtbl = {visitmethod, freemethod}; upb_pbdecodermethod *ret = malloc(sizeof(*ret)); upb_refcounted_init(UPB_UPCAST(ret), &vtbl, &ret); upb_byteshandler_init(&ret->input_handler_); // The method references the group and vice-versa, in a circular reference. upb_ref2(ret, group); upb_ref2(group, ret); upb_inttable_insertptr(&group->methods, dest_handlers, upb_value_ptr(ret)); upb_refcounted_unref(UPB_UPCAST(ret), &ret); ret->group = UPB_UPCAST(group); ret->dest_handlers_ = dest_handlers; ret->is_native_ = false; // If we JIT, it will update this later. upb_inttable_init(&ret->dispatch, UPB_CTYPE_UINT64); if (ret->dest_handlers_) { upb_handlers_ref(ret->dest_handlers_, ret); } return ret; }
upb_enumdef *upb_enumdef_new(const void *owner) { static const struct upb_refcounted_vtbl vtbl = {NULL, &upb_enumdef_free}; upb_enumdef *e = malloc(sizeof(*e)); if (!e) return NULL; if (!upb_def_init(UPB_UPCAST(e), UPB_DEF_ENUM, &vtbl, owner)) goto err2; if (!upb_strtable_init(&e->ntoi, UPB_CTYPE_INT32)) goto err2; if (!upb_inttable_init(&e->iton, UPB_CTYPE_CSTR)) goto err1; return e; err1: upb_strtable_uninit(&e->ntoi); err2: free(e); return NULL; }
upb_msgdef *upb_msgdef_new(const void *owner) { static const struct upb_refcounted_vtbl vtbl = {visitmsg, freemsg}; upb_msgdef *m = malloc(sizeof(*m)); if (!m) return NULL; if (!upb_def_init(UPB_UPCAST(m), UPB_DEF_MSG, &vtbl, owner)) goto err2; if (!upb_inttable_init(&m->itof, UPB_CTYPE_PTR)) goto err2; if (!upb_strtable_init(&m->ntof, UPB_CTYPE_PTR)) goto err1; return m; err1: upb_inttable_uninit(&m->itof); err2: free(m); return NULL; }
const upb_handlers *upb_handlers_newfrozen(const upb_msgdef *m, const void *owner, upb_handlers_callback *callback, void *closure) { dfs_state state; state.callback = callback; state.closure = closure; if (!upb_inttable_init(&state.tab, UPB_CTYPE_PTR)) return NULL; upb_handlers *ret = newformsg(m, owner, &state); upb_inttable_uninit(&state.tab); if (!ret) return NULL; upb_refcounted *r = UPB_UPCAST(ret); bool ok = upb_refcounted_freeze(&r, 1, NULL, UPB_MAX_HANDLER_DEPTH); UPB_ASSERT_VAR(ok, ok); return ret; }
void upb_pbdecodermethod_ref(const upb_pbdecodermethod *m, const void *owner) { upb_refcounted_ref(UPB_UPCAST(m), owner); }