static bool upb_fielddef_resolve(upb_fielddef *f, upb_def *def, upb_status *s) { assert(upb_dyncast_unresolveddef(f->def)); upb_def_unref(f->def); f->def = def; if (f->type == UPB_TYPE(ENUM) && f->default_is_symbolic) { // Resolve the enum's default from a string to an integer. upb_byteregion *bytes = upb_value_getbyteregion(f->defaultval); assert(bytes); // Points to either a real default or the empty string. upb_enumdef *e = upb_downcast_enumdef(f->def); int32_t val = 0; // Could do a sanity check that the default value does not have embedded // NULLs. if (upb_byteregion_len(bytes) == 0) { upb_value_setint32(&f->defaultval, e->defaultval); } else { size_t len; // ptr is guaranteed to be NULL-terminated because the byteregion was // created with upb_byteregion_newl(). const char *ptr = upb_byteregion_getptr(bytes, 0, &len); assert(len == upb_byteregion_len(bytes)); // Should all be in one chunk. bool success = upb_enumdef_ntoi(e, ptr, &val); if (!success) { upb_status_seterrf( s, "Default enum value (%s) is not a member of the enum", ptr); return false; } upb_value_setint32(&f->defaultval, val); } upb_byteregion_free(bytes); } return true; }
bool upb_fielddef_resolvedefault(upb_fielddef *f) { if (!upb_fielddef_default_is_symbolic(f)) return true; upb_byteregion *bytes = upb_value_getbyteregion(f->defaultval); const upb_enumdef *e = upb_downcast_enumdef(upb_fielddef_subdef(f)); assert(bytes); // Points to either a real default or the empty string. assert(e); if (upb_byteregion_len(bytes) == 0) { // The "default default" for an enum is the first defined value. upb_value_setint32(&f->defaultval, e->defaultval); } else { size_t len; int32_t val = 0; // ptr is guaranteed to be NULL-terminated because the byteregion was // created with upb_byteregion_newl(). const char *ptr = upb_byteregion_getptr( bytes, upb_byteregion_startofs(bytes), &len); assert(len == upb_byteregion_len(bytes)); // Should all be in one chunk if (!upb_enumdef_ntoi(e, ptr, &val)) { return false; } upb_value_setint32(&f->defaultval, val); } f->default_is_string = false; upb_byteregion_free(bytes); return true; }
static bool upb_trypullbuf(upb_decoder *d) { assert(upb_decoder_bufleft(d) == 0); upb_decoder_skiptonewbuf(d, upb_decoder_offset(d)); if (upb_byteregion_available(d->input, d->bufstart_ofs) == 0) { switch (upb_byteregion_fetch(d->input)) { case UPB_BYTE_OK: assert(upb_byteregion_available(d->input, d->bufstart_ofs) > 0); break; case UPB_BYTE_EOF: return false; case UPB_BYTE_ERROR: upb_decoder_abortjmp(d, "I/O error in input"); // Decoder resuming is not yet supported. case UPB_BYTE_WOULDBLOCK: upb_decoder_abortjmp(d, "Input returned WOULDBLOCK"); } } size_t len; d->buf = upb_byteregion_getptr(d->input, d->bufstart_ofs, &len); assert(len > 0); d->ptr = d->buf; d->end = d->buf + len; upb_decoder_setmsgend(d); #ifdef UPB_USE_JIT_X64 // If we start parsing a value, we can parse up to 20 bytes without // having to bounds-check anything (2 10-byte varints). Since the // JIT bounds-checks only *between* values (and for strings), the // JIT bails if there are not 20 bytes available. d->jit_end = d->end - 20; #endif assert(upb_decoder_bufleft(d) > 0); return true; }
upb_fielddef *upb_fielddef_dup(const upb_fielddef *f, const void *owner) { upb_fielddef *newf = upb_fielddef_new(owner); if (!newf) return NULL; upb_fielddef_settype(newf, upb_fielddef_type(f)); upb_fielddef_setlabel(newf, upb_fielddef_label(f)); upb_fielddef_setnumber(newf, upb_fielddef_number(f)); upb_fielddef_setname(newf, upb_fielddef_name(f)); if (f->default_is_string) { upb_byteregion *r = upb_value_getbyteregion(upb_fielddef_default(f)); size_t len; const char *ptr = upb_byteregion_getptr(r, 0, &len); assert(len == upb_byteregion_len(r)); upb_fielddef_setdefaultstr(newf, ptr, len); } else { upb_fielddef_setdefault(newf, upb_fielddef_default(f)); } const char *srcname; if (f->subdef_is_symbolic) { srcname = f->sub.name; // Might be NULL. } else { srcname = f->sub.def ? upb_def_fullname(f->sub.def) : NULL; } if (srcname) { char *newname = malloc(strlen(f->sub.def->fullname) + 2); if (!newname) { upb_fielddef_unref(newf, owner); return NULL; } strcpy(newname, "."); strcat(newname, f->sub.def->fullname); upb_fielddef_setsubdefname(newf, newname); free(newname); } return newf; }