summaryrefslogtreecommitdiff
path: root/src/upb_def.c
diff options
context:
space:
mode:
authorJoshua Haberman <joshua@reverberate.org>2011-02-23 10:14:53 -0800
committerJoshua Haberman <joshua@reverberate.org>2011-02-23 10:14:53 -0800
commit3a758132b402e2c4a346d1feb45d00300fed16e7 (patch)
tree804af5b367c9de0349660baac23371ca99544543 /src/upb_def.c
parent6b574175dd43735a26f171de6b34c3f15bb50f12 (diff)
Added proper support for enum default values.
Diffstat (limited to 'src/upb_def.c')
-rw-r--r--src/upb_def.c85
1 files changed, 58 insertions, 27 deletions
diff --git a/src/upb_def.c b/src/upb_def.c
index d77e29a..b12ed14 100644
--- a/src/upb_def.c
+++ b/src/upb_def.c
@@ -495,9 +495,14 @@ static upb_flow_t upb_enumdef_EnumValueDescriptorProto_endmsg(void *_b) {
upb_seterr(&b->status, UPB_ERROR, "Enum value missing name or number.");
return UPB_BREAK;
}
+ upb_enumdef *e = upb_downcast_enumdef(upb_defbuilder_last(b));
+ if (upb_inttable_count(&e->iton) == 0) {
+ // The default value of an enum (in the absence of an explicit default) is
+ // its first listed value.
+ e->default_value = b->number;
+ }
upb_ntoi_ent ntoi_ent = {{b->name, 0}, b->number};
upb_iton_ent iton_ent = {0, b->name};
- upb_enumdef *e = upb_downcast_enumdef(upb_defbuilder_last(b));
upb_strtable_insert(&e->ntoi, &ntoi_ent.e);
upb_inttable_insert(&e->iton, b->number, &iton_ent);
// We don't unref "name" because we pass our ref to the iton entry of the
@@ -530,8 +535,16 @@ static upb_flow_t upb_enumdef_EnumDescriptorProto_startmsg(void *_b) {
}
static upb_flow_t upb_enumdef_EnumDescriptorProto_endmsg(void *_b) {
- (void)_b;
- assert(upb_defbuilder_last((upb_defbuilder*)_b)->fqname != NULL);
+ upb_defbuilder *b = _b;
+ upb_enumdef *e = upb_downcast_enumdef(upb_defbuilder_last(b));
+ if (upb_defbuilder_last((upb_defbuilder*)_b)->fqname == NULL) {
+ upb_seterr(&b->status, UPB_ERROR, "Enum had no name.");
+ return UPB_BREAK;
+ }
+ if (upb_inttable_count(&e->iton) == 0) {
+ upb_seterr(&b->status, UPB_ERROR, "Enum had no values.");
+ return UPB_BREAK;
+ }
return UPB_CONTINUE;
}
@@ -593,11 +606,18 @@ upb_string *upb_enumdef_iton(upb_enumdef *def, upb_enumval_t num) {
return e ? e->string : NULL;
}
+bool upb_enumdef_ntoi(upb_enumdef *def, upb_string *name, upb_enumval_t *num) {
+ upb_ntoi_ent *e = (upb_ntoi_ent*)upb_strtable_lookup(&def->ntoi, name);
+ if (!e) return false;
+ *num = e->value;
+ return true;
+}
+
/* upb_fielddef ***************************************************************/
static void upb_fielddef_free(upb_fielddef *f) {
- if (upb_isstring(f) || f->type == UPB_TYPE(ENUM)) {
+ if (upb_isstring(f)) {
upb_string_unref(upb_value_getstr(f->default_value));
} else if (upb_issubmsg(f)) {
upb_msg *m = upb_value_getmsg(f->default_value);
@@ -617,6 +637,36 @@ static void upb_fielddef_free(upb_fielddef *f) {
free(f);
}
+static bool upb_fielddef_resolve(upb_fielddef *f, upb_def *def, upb_status *s) {
+ if(f->owned) upb_def_unref(f->def);
+ f->def = def;
+ // We will later make the ref unowned if it is a part of a cycle.
+ f->owned = true;
+ upb_def_ref(def);
+ if (upb_issubmsg(f)) {
+ upb_msgdef *md = upb_downcast_msgdef(def);
+ upb_value_setmsg(&f->default_value, upb_msg_getref(md->default_message));
+ } else if (f->type == UPB_TYPE(ENUM)) {
+ upb_string *str = upb_value_getstr(f->default_value);
+ assert(str); // Should point to either a real default or the empty string.
+ upb_enumdef *e = upb_downcast_enumdef(f->def);
+ upb_enumval_t val;
+ if (str == upb_emptystring()) {
+ upb_value_setint32(&f->default_value, e->default_value);
+ } else {
+ bool success = upb_enumdef_ntoi(e, str, &val);
+ upb_string_unref(str);
+ if (!success) {
+ upb_seterr(s, UPB_ERROR, "Default enum value (" UPB_STRFMT ") is not a "
+ "member of the enum", UPB_STRARG(str));
+ return false;
+ }
+ upb_value_setint32(&f->default_value, val);
+ }
+ }
+ return true;
+}
+
static upb_flow_t upb_fielddef_startmsg(void *_b) {
upb_defbuilder *b = _b;
upb_fielddef *f = malloc(sizeof(*f));
@@ -645,10 +695,7 @@ static bool upb_fielddef_setdefault(upb_string *dstr, upb_value *d, int type) {
} else if (type == UPB_TYPE(MESSAGE) || type == UPB_TYPE(GROUP)) {
// We don't expect to get a default value.
upb_string_unref(dstr);
- if (dstr != NULL) {
- printf("Returning false because I got a default string for a message!\n");
- success = false;
- }
+ if (dstr != NULL) success = false;
} else {
// The strto* functions need the string to be NULL-terminated.
char *strz = upb_string_isempty(dstr) ? NULL : upb_string_newcstr(dstr);
@@ -724,9 +771,6 @@ static bool upb_fielddef_setdefault(upb_string *dstr, upb_value *d, int type) {
success = false;
break;
}
- if (!success) {
- printf("Returning false on the int conversion path, was trying to convert: %s, type=%d\n", strz, type);
- }
free(strz);
}
return success;
@@ -761,10 +805,10 @@ static upb_flow_t upb_fielddef_value(void *_b, upb_fielddef *f, upb_value val) {
upb_defbuilder *b = _b;
switch(f->number) {
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_FIELDNUM:
- b->f->type = upb_value_getenumval(val);
+ b->f->type = upb_value_getint32(val);
break;
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL_FIELDNUM:
- b->f->label = upb_value_getenumval(val);
+ b->f->label = upb_value_getint32(val);
break;
case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NUMBER_FIELDNUM:
b->f->number = upb_value_getint32(val);
@@ -966,19 +1010,6 @@ static void upb_msgdef_free(upb_msgdef *m)
free(m);
}
-static void upb_msgdef_resolve(upb_msgdef *m, upb_fielddef *f, upb_def *def) {
- (void)m;
- if(f->owned) upb_def_unref(f->def);
- f->def = def;
- // We will later make the ref unowned if it is a part of a cycle.
- f->owned = true;
- upb_def_ref(def);
- if (upb_issubmsg(f)) {
- upb_msgdef *md = upb_downcast_msgdef(def);
- upb_value_setmsg(&f->default_value, upb_msg_getref(md->default_message));
- }
-}
-
upb_msg_iter upb_msg_begin(upb_msgdef *m) {
return upb_inttable_begin(&m->itof);
}
@@ -1133,7 +1164,7 @@ bool upb_resolverefs(upb_strtable *tmptab, upb_strtable *symtab,
upb_seterr(status, UPB_ERROR, "Unexpected type");
return false;
}
- upb_msgdef_resolve(m, f, found->def);
+ if (!upb_fielddef_resolve(f, found->def, status)) return false;
}
}
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback