|
|
|
@ -8,6 +8,7 @@ |
|
|
|
|
#include <stdlib.h> |
|
|
|
|
#include <stddef.h> |
|
|
|
|
#include <string.h> |
|
|
|
|
#include "upb/bytestream.h" |
|
|
|
|
#include "upb/def.h" |
|
|
|
|
|
|
|
|
|
#define alignof(t) offsetof(struct { char c; t x; }, x) |
|
|
|
@ -194,42 +195,77 @@ const char *upb_enumdef_iton(upb_enumdef *def, int32_t num) { |
|
|
|
|
return e ? e->str : NULL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool upb_enumdef_ntoil(upb_enumdef *def, char *name, size_t len, int32_t *num) { |
|
|
|
|
bool upb_enumdef_ntoil(upb_enumdef *def, const char *name, size_t len, int32_t *num) { |
|
|
|
|
upb_ntoi_ent *e = upb_strtable_lookupl(&def->ntoi, name, len); |
|
|
|
|
if (!e) return false; |
|
|
|
|
if (num) *num = e->value; |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool upb_enumdef_ntoi(upb_enumdef *e, char *name, int32_t *num) { |
|
|
|
|
bool upb_enumdef_ntoi(upb_enumdef *e, const char *name, int32_t *num) { |
|
|
|
|
return upb_enumdef_ntoil(e, name, strlen(name), num); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* upb_fielddef ***************************************************************/ |
|
|
|
|
|
|
|
|
|
static void upb_fielddef_init_default(upb_fielddef *f); |
|
|
|
|
|
|
|
|
|
upb_fielddef *upb_fielddef_new() { |
|
|
|
|
upb_fielddef *f = malloc(sizeof(*f)); |
|
|
|
|
f->msgdef = NULL; |
|
|
|
|
f->def = NULL; |
|
|
|
|
upb_atomic_init(&f->refcount, 1); |
|
|
|
|
f->finalized = false; |
|
|
|
|
f->type = 0; |
|
|
|
|
f->label = UPB_LABEL(OPTIONAL); |
|
|
|
|
f->hasbit = -1; |
|
|
|
|
f->offset = 0; |
|
|
|
|
f->number = 0; // not a valid field number.
|
|
|
|
|
f->hasdefault = false; |
|
|
|
|
f->name = NULL; |
|
|
|
|
f->accessor = NULL; |
|
|
|
|
upb_value_setfielddef(&f->fval, f); |
|
|
|
|
|
|
|
|
|
// These are initialized to be invalid; the user must set them explicitly.
|
|
|
|
|
// Could relax this later if it's convenient and non-confusing to have a
|
|
|
|
|
// defaults for them.
|
|
|
|
|
f->name = NULL; |
|
|
|
|
f->type = 0; |
|
|
|
|
f->number = 0; |
|
|
|
|
|
|
|
|
|
upb_fielddef_init_default(f); |
|
|
|
|
return f; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void upb_fielddef_free(upb_fielddef *f) { |
|
|
|
|
if (upb_isstring(f)) { |
|
|
|
|
free(upb_value_getptr(f->defaultval)); |
|
|
|
|
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_setstrref(&f->defaultval, upb_strref_new("")); break; |
|
|
|
|
case UPB_TYPE(GROUP): |
|
|
|
|
case UPB_TYPE(MESSAGE): upb_value_setptr(&f->defaultval, NULL); break; |
|
|
|
|
} |
|
|
|
|
f->default_is_symbolic = false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void upb_fielddef_uninit_default(upb_fielddef *f) { |
|
|
|
|
if (upb_isstring(f) || f->default_is_symbolic) { |
|
|
|
|
upb_strref_free((upb_strref*)upb_value_getstrref(f->defaultval)); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void upb_fielddef_free(upb_fielddef *f) { |
|
|
|
|
upb_fielddef_uninit_default(f); |
|
|
|
|
if (f->def) { |
|
|
|
|
// We own a ref on the subdef iff we are not part of a msgdef.
|
|
|
|
|
if (f->msgdef == NULL) { |
|
|
|
@ -286,17 +322,18 @@ 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)) { |
|
|
|
|
if (f->type == UPB_TYPE(ENUM) && f->default_is_symbolic) { |
|
|
|
|
// Resolve the enum's default from a string to an integer.
|
|
|
|
|
char *str = upb_value_getptr(f->defaultval); |
|
|
|
|
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; |
|
|
|
|
if (str[0] == '\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, &val); |
|
|
|
|
free(str); |
|
|
|
|
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); |
|
|
|
@ -304,6 +341,7 @@ static bool upb_fielddef_resolve(upb_fielddef *f, upb_def *def, upb_status *s) { |
|
|
|
|
} |
|
|
|
|
upb_value_setint32(&f->defaultval, val); |
|
|
|
|
} |
|
|
|
|
upb_strref_free(str); |
|
|
|
|
} |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
@ -323,7 +361,9 @@ bool upb_fielddef_setname(upb_fielddef *f, const char *name) { |
|
|
|
|
|
|
|
|
|
bool upb_fielddef_settype(upb_fielddef *f, uint8_t type) { |
|
|
|
|
assert(!f->finalized); |
|
|
|
|
upb_fielddef_uninit_default(f); |
|
|
|
|
f->type = type; |
|
|
|
|
upb_fielddef_init_default(f); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -335,10 +375,23 @@ bool upb_fielddef_setlabel(upb_fielddef *f, uint8_t label) { |
|
|
|
|
|
|
|
|
|
void upb_fielddef_setdefault(upb_fielddef *f, upb_value value) { |
|
|
|
|
assert(!f->finalized); |
|
|
|
|
// TODO: string ownership?
|
|
|
|
|
assert(!upb_isstring(f)); |
|
|
|
|
f->defaultval = value; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
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; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void upb_fielddef_setdefaultcstr(upb_fielddef *f, const char *str) { |
|
|
|
|
upb_fielddef_setdefaultstr(f, str, str ? strlen(str) : 0); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void upb_fielddef_setfval(upb_fielddef *f, upb_value fval) { |
|
|
|
|
assert(!f->finalized); |
|
|
|
|
// TODO: string ownership?
|
|
|
|
@ -728,30 +781,6 @@ bool upb_symtab_add(upb_symtab *s, upb_def **defs, int n, upb_status *status) { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Set default default if none was set explicitly.
|
|
|
|
|
if (!f->hasdefault) { |
|
|
|
|
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(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(ENUM): // Will be resolved by upb_resolve().
|
|
|
|
|
case UPB_TYPE(STRING): |
|
|
|
|
case UPB_TYPE(BYTES): |
|
|
|
|
case UPB_TYPE(GROUP): |
|
|
|
|
case UPB_TYPE(MESSAGE): break; // do nothing for now.
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!upb_hassubdef(f)) continue; // No resolving necessary.
|
|
|
|
|
upb_downcast_unresolveddef(f->def); // Type check.
|
|
|
|
|
const char *name = f->def->fqname; |
|
|
|
|