bool upb_sink_endsubmsg(upb_sink *s, upb_selector_t sel) { upb_endmsg_handler *endmsg = (upb_endmsg_handler *)upb_handlers_gethandler( s->top->h, UPB_ENDMSG_SELECTOR); if (endmsg) { // TODO(haberman): check return value. const void *hd = upb_handlers_gethandlerdata(s->top->h, UPB_ENDMSG_SELECTOR); endmsg(s->top->closure, hd, &s->pipeline_->status_); } --s->top; assert(sel == s->top->selector); const upb_handlers *h = s->top->h; upb_endfield_handler *endsubmsg = (upb_endfield_handler*)upb_handlers_gethandler(h, sel); if (endsubmsg) { const void *hd = upb_handlers_gethandlerdata(h, sel); bool ok = endsubmsg(s->top->closure, hd); if (!ok) { ++s->top; return false; } } return true; }
bool upb_handlers_getattr(const upb_handlers *h, upb_selector_t sel, upb_handlerattr *attr) { if (!upb_handlers_gethandler(h, sel)) return false; *attr = h->table[sel].attr; return true; }
bool upb_sink_startsubmsg(upb_sink *s, upb_selector_t sel) { if (!chkstack(s)) return false; void *subc = s->top->closure; const upb_handlers *h = s->top->h; upb_startfield_handler *startsubmsg = (upb_startfield_handler*)upb_handlers_gethandler(h, sel); if (startsubmsg) { const void *hd = upb_handlers_gethandlerdata(h, sel); subc = startsubmsg(s->top->closure, hd); if (subc == UPB_BREAK) { return false; } } s->top->selector= upb_handlers_getendselector(sel); ++s->top; s->top->h = upb_handlers_getsubhandlers_sel(h, sel); // TODO: should add support for submessages without any handlers assert(s->top->h); s->top->closure = subc; upb_sink_startmsg(s); return true; }
bool upb_sink_startmsg(upb_sink *s) { const upb_handlers *h = s->top->h; upb_startmsg_handler *startmsg = (upb_startmsg_handler *)upb_handlers_gethandler(h, UPB_STARTMSG_SELECTOR); if (startmsg) { const void *hd = upb_handlers_gethandlerdata(h, UPB_STARTMSG_SELECTOR); bool ok = startmsg(s->top->closure, hd); if (!ok) return false; } return true; }
bool upb_sink_endmsg(upb_sink *s) { assert(s->top == s->stack); const upb_handlers *h = s->top->h; upb_endmsg_handler *endmsg = (upb_endmsg_handler *)upb_handlers_gethandler(h, UPB_ENDMSG_SELECTOR); if (endmsg) { const void *hd = upb_handlers_gethandlerdata(h, UPB_ENDMSG_SELECTOR); bool ok = endmsg(s->top->closure, hd, &s->pipeline_->status_); if (!ok) return false; } return true; }
size_t upb_sink_putstring(upb_sink *s, upb_selector_t sel, const char *buf, size_t n) { const upb_handlers *h = s->top->h; upb_string_handler *handler = (upb_string_handler*)upb_handlers_gethandler(h, sel); if (handler) { const void *hd = upb_handlers_gethandlerdata(h, sel);; n = handler(s->top->closure, hd, buf, n); } return n; }
bool upb_sink_endstr(upb_sink *s, upb_selector_t sel) { --s->top; assert(sel == s->top->selector); const upb_handlers *h = s->top->h; upb_endfield_handler *endstr = (upb_endfield_handler*)upb_handlers_gethandler(h, sel); if (endstr) { const void *hd = upb_handlers_gethandlerdata(h, sel); bool ok = endstr(s->top->closure, hd); if (!ok) { ++s->top; return false; } } return true; }
bool upb_sink_startstr(upb_sink *s, upb_selector_t sel, size_t size_hint) { if (!chkstack(s)) return false; void *subc = s->top->closure; const upb_handlers *h = s->top->h; upb_startstr_handler *startstr = (upb_startstr_handler*)upb_handlers_gethandler(h, sel); if (startstr) { const void *hd = upb_handlers_gethandlerdata(h, sel); subc = startstr(s->top->closure, hd, size_hint); if (subc == UPB_BREAK) { return false; } } s->top->selector = upb_handlers_getendselector(sel); ++s->top; s->top->h = h; s->top->closure = subc; return true; }
const upb_shim_data *upb_shim_getdata(const upb_handlers *h, upb_selector_t s, upb_fieldtype_t *type) { upb_func *f = upb_handlers_gethandler(h, s); if ((upb_int64_handlerfunc*)f == upb_shim_setint64) { *type = UPB_TYPE_INT64; } else if ((upb_int32_handlerfunc*)f == upb_shim_setint32) { *type = UPB_TYPE_INT32; } else if ((upb_uint64_handlerfunc*)f == upb_shim_setuint64) { *type = UPB_TYPE_UINT64; } else if ((upb_uint32_handlerfunc*)f == upb_shim_setuint32) { *type = UPB_TYPE_UINT32; } else if ((upb_double_handlerfunc*)f == upb_shim_setdouble) { *type = UPB_TYPE_DOUBLE; } else if ((upb_float_handlerfunc*)f == upb_shim_setfloat) { *type = UPB_TYPE_FLOAT; } else if ((upb_bool_handlerfunc*)f == upb_shim_setbool) { *type = UPB_TYPE_BOOL; } else { return NULL; } return (const upb_shim_data*)upb_handlers_gethandlerdata(h, s); }
bool upb_handlers_freeze(upb_handlers *const*handlers, int n, upb_status *s) { // TODO: verify we have a transitive closure. for (int i = 0; i < n; i++) { upb_handlers *h = handlers[i]; if (!upb_ok(&h->status_)) { upb_status_seterrf(s, "handlers for message %s had error status: %s", upb_msgdef_fullname(upb_handlers_msgdef(h)), upb_status_errmsg(&h->status_)); return false; } // Check that there are no closure mismatches due to missing Start* handlers // or subhandlers with different type-level types. upb_msg_iter j; for(upb_msg_begin(&j, h->msg); !upb_msg_done(&j); upb_msg_next(&j)) { const upb_fielddef *f = upb_msg_iter_field(&j); if (upb_fielddef_isseq(f)) { if (!checkstart(h, f, UPB_HANDLER_STARTSEQ, s)) return false; } if (upb_fielddef_isstring(f)) { if (!checkstart(h, f, UPB_HANDLER_STARTSTR, s)) return false; } if (upb_fielddef_issubmsg(f)) { bool hashandler = false; if (upb_handlers_gethandler(h, getsel(h, f, UPB_HANDLER_STARTSUBMSG)) || upb_handlers_gethandler(h, getsel(h, f, UPB_HANDLER_ENDSUBMSG))) { hashandler = true; } if (upb_fielddef_isseq(f) && (upb_handlers_gethandler(h, getsel(h, f, UPB_HANDLER_STARTSEQ)) || upb_handlers_gethandler(h, getsel(h, f, UPB_HANDLER_ENDSEQ)))) { hashandler = true; } if (hashandler && !upb_handlers_getsubhandlers(h, f)) { // For now we add an empty subhandlers in this case. It makes the // decoder code generator simpler, because it only has to handle two // cases (submessage has handlers or not) as opposed to three // (submessage has handlers in enclosing message but no subhandlers). // // This makes parsing less efficient in the case that we want to // notice a submessage but skip its contents (like if we're testing // for submessage presence or counting the number of repeated // submessages). In this case we will end up parsing the submessage // field by field and throwing away the results for each, instead of // skipping the whole delimited thing at once. If this is an issue we // can revisit it, but do remember that this only arises when you have // handlers (startseq/startsubmsg/endsubmsg/endseq) set for the // submessage but no subhandlers. The uses cases for this are // limited. upb_handlers *sub = upb_handlers_new(upb_fielddef_msgsubdef(f), &sub); upb_handlers_setsubhandlers(h, f, sub); upb_handlers_unref(sub, &sub); } // TODO(haberman): check type of submessage. // This is slightly tricky; also consider whether we should check that // they match at setsubhandlers time. } } } if (!upb_refcounted_freeze((upb_refcounted*const*)handlers, n, s, UPB_MAX_HANDLER_DEPTH)) { return false; } return true; }