static bool upb_subdef_typecheck(upb_fielddef *f, const upb_def *subdef) { if (f->type_ == UPB_TYPE(MESSAGE) || f->type_ == UPB_TYPE(GROUP)) return upb_dyncast_msgdef(subdef) != NULL; else if (f->type_ == UPB_TYPE(ENUM)) return upb_dyncast_enumdef(subdef) != NULL; else { assert(false); return false; } }
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; }
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_strref *str = (upb_strref*)upb_value_getstrref(f->defaultval); assert(str); // Should point 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 (str->ptr[0] == '\0') { upb_value_setint32(&f->defaultval, e->defaultval); } else { bool success = upb_enumdef_ntoi(e, str->ptr, &val); if (!success) { upb_status_seterrf( s, "Default enum value (%s) is not a member of the enum", str); return false; } upb_value_setint32(&f->defaultval, val); } upb_strref_free(str); } return true; }
static void field_endmsg(void *_r, upb_status *status) { upb_descreader *r = _r; upb_fielddef *f = r->f; // TODO: verify that all required fields were present. assert(upb_fielddef_number(f) != 0 && upb_fielddef_name(f) != NULL); assert((upb_fielddef_subdefname(f) != NULL) == upb_fielddef_hassubdef(f)); if (r->default_string) { if (upb_fielddef_issubmsg(f)) { upb_status_seterrliteral(status, "Submessages cannot have defaults."); return; } if (upb_fielddef_isstring(f) || upb_fielddef_type(f) == UPB_TYPE(ENUM)) { upb_fielddef_setdefaultcstr(f, r->default_string); } else { upb_value val; upb_value_setptr(&val, NULL); // Silence inaccurate compiler warnings. if (!parse_default(r->default_string, &val, upb_fielddef_type(f))) { // We don't worry too much about giving a great error message since the // compiler should have ensured this was correct. upb_status_seterrliteral(status, "Error converting default value."); return; } upb_fielddef_setdefault(f, val); } } }
void upb_fielddef_setdefaultstr(upb_fielddef *f, const void *str, size_t len) { assert(upb_isstring(f) || f->type == UPB_TYPE(ENUM)); upb_byteregion *bytes = upb_value_getbyteregion(f->defaultval); assert(bytes); upb_byteregion_free(bytes); upb_value_setbyteregion(&f->defaultval, upb_byteregion_newl(str, len)); f->default_is_symbolic = true; }
void upb_fielddef_setdefaultstr(upb_fielddef *f, const void *str, size_t len) { assert(upb_isstring(f) || f->type == UPB_TYPE(ENUM)); const upb_strref *ref = upb_value_getstrref(f->defaultval); assert(ref); upb_strref_free((upb_strref*)ref); upb_value_setstrref(&f->defaultval, upb_strref_newl(str, len)); f->default_is_symbolic = true; }
bool upb_fielddef_setdefaultstr(upb_fielddef *f, const void *str, size_t len) { assert(upb_fielddef_isstring(f) || f->type_ == UPB_TYPE(ENUM)); if (f->type_ == UPB_TYPE(ENUM) && !upb_isident(str, len, false)) return false; if (f->default_is_string) { upb_byteregion *bytes = upb_value_getbyteregion(f->defaultval); assert(bytes); upb_byteregion_free(bytes); } else { assert(f->type_ == UPB_TYPE(ENUM)); } upb_byteregion *r = upb_byteregion_newl(str, len); upb_value_setbyteregion(&f->defaultval, r); upb_bytesuccess_t ret = upb_byteregion_fetch(r); UPB_ASSERT_VAR(ret, ret == (len == 0 ? UPB_BYTE_EOF : UPB_BYTE_OK)); assert(upb_byteregion_available(r, 0) == upb_byteregion_len(r)); f->default_is_string = true; return true; }
PyMODINIT_FUNC initupb(void) { PyObject *mod = Py_InitModule("upb", methods); PyUpb_AddType(mod, "FieldDef", &PyUpb_FieldDefType); PyUpb_AddType(mod, "MessageDef", &PyUpb_MessageDefType); PyUpb_AddType(mod, "SymbolTable", &PyUpb_SymbolTableType); PyModule_AddIntConstant(mod, "LABEL_OPTIONAL", UPB_LABEL(OPTIONAL)); PyModule_AddIntConstant(mod, "LABEL_REQUIRED", UPB_LABEL(REQUIRED)); PyModule_AddIntConstant(mod, "LABEL_REPEATED", UPB_LABEL(REPEATED)); PyModule_AddIntConstant(mod, "TYPE_DOUBLE", UPB_TYPE(DOUBLE)); PyModule_AddIntConstant(mod, "TYPE_FLOAT", UPB_TYPE(FLOAT)); PyModule_AddIntConstant(mod, "TYPE_INT64", UPB_TYPE(INT64)); PyModule_AddIntConstant(mod, "TYPE_UINT64", UPB_TYPE(UINT64)); PyModule_AddIntConstant(mod, "TYPE_INT32", UPB_TYPE(INT32)); PyModule_AddIntConstant(mod, "TYPE_FIXED64", UPB_TYPE(FIXED64)); PyModule_AddIntConstant(mod, "TYPE_FIXED32", UPB_TYPE(FIXED32)); PyModule_AddIntConstant(mod, "TYPE_BOOL", UPB_TYPE(BOOL)); PyModule_AddIntConstant(mod, "TYPE_STRING", UPB_TYPE(STRING)); PyModule_AddIntConstant(mod, "TYPE_GROUP", UPB_TYPE(GROUP)); PyModule_AddIntConstant(mod, "TYPE_MESSAGE", UPB_TYPE(MESSAGE)); PyModule_AddIntConstant(mod, "TYPE_BYTES", UPB_TYPE(BYTES)); PyModule_AddIntConstant(mod, "TYPE_UINT32", UPB_TYPE(UINT32)); PyModule_AddIntConstant(mod, "TYPE_ENUM", UPB_TYPE(ENUM)); PyModule_AddIntConstant(mod, "TYPE_SFIXED32", UPB_TYPE(SFIXED32)); PyModule_AddIntConstant(mod, "TYPE_SFIXED64", UPB_TYPE(SFIXED64)); PyModule_AddIntConstant(mod, "TYPE_SINT32", UPB_TYPE(SINT32)); PyModule_AddIntConstant(mod, "TYPE_SINT64", UPB_TYPE(SINT64)); obj_cache = PyDict_New(); reverse_cache = PyDict_New(); static PyMethodDef method = { "WeakRefCallback", &PyUpb_ObjCacheDeleteCallback, METH_O, NULL}; PyObject *pyname = PyString_FromString(method.ml_name); weakref_callback = PyCFunction_NewEx(&method, NULL, pyname); Py_DECREF(pyname); }
static upb_accessor_vtbl *PyUpb_AccessorForField(upb_fielddef *f) { switch (f->type) { case UPB_TYPE(DOUBLE): RETURN_STDMSG(double, 8) case UPB_TYPE(FLOAT): RETURN_STDMSG(float, 4) case UPB_TYPE(UINT64): case UPB_TYPE(FIXED64): RETURN_STDMSG(uint64, 8) case UPB_TYPE(INT64): case UPB_TYPE(SFIXED64): case UPB_TYPE(SINT64): RETURN_STDMSG(int64, 8) case UPB_TYPE(INT32): case UPB_TYPE(SINT32): case UPB_TYPE(ENUM): case UPB_TYPE(SFIXED32): RETURN_STDMSG(int32, 4) case UPB_TYPE(UINT32): case UPB_TYPE(FIXED32): RETURN_STDMSG(uint32, 4) case UPB_TYPE(BOOL): { STDMSG(bool, 1); return &vtbl; } case UPB_TYPE(GROUP): case UPB_TYPE(MESSAGE): RETURN_STDMSG(ptr, 8) // TODO: 32-bit case UPB_TYPE(STRING): case UPB_TYPE(BYTES): { STDMSG(ptr, 8); vtbl.set = &PyUpb_Message_StringValue; vtbl.append = &PyUpb_Message_AppendStringValue; return &vtbl; } } return NULL; }
static upb_flow_t upb_textprinter_value(void *_p, upb_value fval, upb_value val) { upb_textprinter *p = _p; upb_fielddef *f = upb_value_getfielddef(fval); upb_textprinter_indent(p); CHECK(upb_bytesink_printf(p->bytesink, &p->status, UPB_STRFMT ": ", UPB_STRARG(f->name))); #define CASE(fmtstr, member) \ CHECK(upb_bytesink_printf(p->bytesink, &p->status, fmtstr, upb_value_get ## member(val))); break; switch(f->type) { case UPB_TYPE(DOUBLE): CASE("%0.f", double); case UPB_TYPE(FLOAT): CASE("%0.f", float) case UPB_TYPE(INT64): case UPB_TYPE(SFIXED64): case UPB_TYPE(SINT64): CASE("%" PRId64, int64) case UPB_TYPE(UINT64): case UPB_TYPE(FIXED64): CASE("%" PRIu64, uint64) case UPB_TYPE(UINT32): case UPB_TYPE(FIXED32): CASE("%" PRIu32, uint32); case UPB_TYPE(ENUM): { upb_enumdef *enum_def = upb_downcast_enumdef(f->def); upb_string *enum_label = upb_enumdef_iton(enum_def, upb_value_getint32(val)); if (enum_label) { // We found a corresponding string for this enum. Otherwise we fall // through to the int32 code path. CHECK(upb_bytesink_putstr(p->bytesink, enum_label, &p->status)); break; } } case UPB_TYPE(INT32): case UPB_TYPE(SFIXED32): case UPB_TYPE(SINT32): CASE("%" PRId32, int32) case UPB_TYPE(BOOL): CASE("%hhu", bool); case UPB_TYPE(STRING): case UPB_TYPE(BYTES): CHECK(upb_bytesink_putstr(p->bytesink, UPB_STRLIT("\""), &p->status)); CHECK(upb_textprinter_putescaped(p, upb_value_getstr(val), f->type == UPB_TYPE(STRING))); CHECK(upb_bytesink_putstr(p->bytesink, UPB_STRLIT("\""), &p->status)); break; } upb_textprinter_endfield(p); return UPB_CONTINUE; err: return UPB_BREAK; }
upb_accessor_vtbl *upb_stdmsg_accessor(upb_fielddef *f) { switch (f->type) { case UPB_TYPE(DOUBLE): STDMSG(double, 8) case UPB_TYPE(FLOAT): STDMSG(float, 4) case UPB_TYPE(UINT64): case UPB_TYPE(FIXED64): STDMSG(uint64, 8) case UPB_TYPE(INT64): case UPB_TYPE(SFIXED64): case UPB_TYPE(SINT64): STDMSG(int64, 8) case UPB_TYPE(INT32): case UPB_TYPE(SINT32): case UPB_TYPE(ENUM): case UPB_TYPE(SFIXED32): STDMSG(int32, 4) case UPB_TYPE(UINT32): case UPB_TYPE(FIXED32): STDMSG(uint32, 4) case UPB_TYPE(BOOL): STDMSG(bool, 1) case UPB_TYPE(STRING): case UPB_TYPE(BYTES): case UPB_TYPE(GROUP): case UPB_TYPE(MESSAGE): STDMSG(str, 8) // TODO: 32-bit } return NULL; }
static void upb_fielddef_init_default(upb_fielddef *f) { switch (upb_fielddef_type(f)) { case UPB_TYPE(DOUBLE): upb_value_setdouble(&f->defaultval, 0); break; case UPB_TYPE(FLOAT): upb_value_setfloat(&f->defaultval, 0); break; case UPB_TYPE(UINT64): case UPB_TYPE(FIXED64): upb_value_setuint64(&f->defaultval, 0); break; case UPB_TYPE(INT64): case UPB_TYPE(SFIXED64): case UPB_TYPE(SINT64): upb_value_setint64(&f->defaultval, 0); break; case UPB_TYPE(ENUM): case UPB_TYPE(INT32): case UPB_TYPE(SINT32): case UPB_TYPE(SFIXED32): upb_value_setint32(&f->defaultval, 0); break; case UPB_TYPE(UINT32): case UPB_TYPE(FIXED32): upb_value_setuint32(&f->defaultval, 0); break; case UPB_TYPE(BOOL): upb_value_setbool(&f->defaultval, false); break; case UPB_TYPE(STRING): case UPB_TYPE(BYTES): upb_value_setbyteregion(&f->defaultval, upb_byteregion_new("")); break; case UPB_TYPE(GROUP): case UPB_TYPE(MESSAGE): upb_value_setptr(&f->defaultval, NULL); break; } f->default_is_symbolic = false; }
// Converts the default value in string "str" into "d". Passes a ref on str. // Returns true on success. static bool parse_default(char *str, upb_value *d, int type) { bool success = true; if (str) { switch(type) { case UPB_TYPE(INT32): case UPB_TYPE(SINT32): case UPB_TYPE(SFIXED32): upb_value_setint32(d, 0); break; case UPB_TYPE(INT64): case UPB_TYPE(SINT64): case UPB_TYPE(SFIXED64): upb_value_setint64(d, 0); break; case UPB_TYPE(UINT32): case UPB_TYPE(FIXED32): upb_value_setuint32(d, 0); case UPB_TYPE(UINT64): case UPB_TYPE(FIXED64): upb_value_setuint64(d, 0); break; case UPB_TYPE(DOUBLE): upb_value_setdouble(d, 0); break; case UPB_TYPE(FLOAT): upb_value_setfloat(d, 0); break; case UPB_TYPE(BOOL): upb_value_setbool(d, false); break; default: abort(); } } else { char *end; switch (type) { case UPB_TYPE(INT32): case UPB_TYPE(SINT32): case UPB_TYPE(SFIXED32): { long val = strtol(str, &end, 0); if (val > INT32_MAX || val < INT32_MIN || errno == ERANGE || *end) success = false; else upb_value_setint32(d, val); break; } case UPB_TYPE(INT64): case UPB_TYPE(SINT64): case UPB_TYPE(SFIXED64): upb_value_setint64(d, strtoll(str, &end, 0)); if (errno == ERANGE || *end) success = false; break; case UPB_TYPE(UINT32): case UPB_TYPE(FIXED32): { unsigned long val = strtoul(str, &end, 0); if (val > UINT32_MAX || errno == ERANGE || *end) success = false; else upb_value_setuint32(d, val); break; } case UPB_TYPE(UINT64): case UPB_TYPE(FIXED64): upb_value_setuint64(d, strtoull(str, &end, 0)); if (errno == ERANGE || *end) success = false; break; case UPB_TYPE(DOUBLE): upb_value_setdouble(d, strtod(str, &end)); if (errno == ERANGE || *end) success = false; break; case UPB_TYPE(FLOAT): upb_value_setfloat(d, strtof(str, &end)); if (errno == ERANGE || *end) success = false; break; case UPB_TYPE(BOOL): { if (strcmp(str, "false") == 0) upb_value_setbool(d, false); else if (strcmp(str, "true") == 0) upb_value_setbool(d, true); else success = false; } default: abort(); } } return success; }
bool upb_fielddef_hassubdef(const upb_fielddef *f) { return upb_fielddef_issubmsg(f) || upb_fielddef_type(f) == UPB_TYPE(ENUM); }