upb_enumdef *upb_enumdef_dup(const upb_enumdef *e) { upb_enumdef *new_e = upb_enumdef_new(); upb_enum_iter i; for(i = upb_enum_begin(e); !upb_enum_done(i); i = upb_enum_next(e, i)) { assert(upb_enumdef_addval(new_e, upb_enum_iter_name(i), upb_enum_iter_number(i))); } return new_e; }
/* * call-seq: * EnumDescriptor.add_value(key, value) * * Adds a new key => value mapping to this enum type. Key must be given as a * Ruby symbol. Cannot be called if the enum type has already been added to a * pool. Will raise an exception if the key or value is already in use. */ VALUE EnumDescriptor_add_value(VALUE _self, VALUE name, VALUE number) { DEFINE_SELF(EnumDescriptor, self, _self); upb_enumdef* mut_def = check_enum_notfrozen(self->enumdef); const char* name_str = rb_id2name(SYM2ID(name)); int32_t val = NUM2INT(number); CHECK_UPB(upb_enumdef_addval(mut_def, name_str, val, &status), "Error adding value to enum"); return Qnil; }
static void test_replacement() { upb_symtab *s = upb_symtab_new(&s); upb_enumdef *e2; upb_msgdef *m2; upb_enumdef *e; upb_status status = UPB_STATUS_INIT; upb_def *newdefs[3]; upb_def *newdefs2[1]; const upb_msgdef *m3; upb_msgdef *m = upb_msgdef_newnamed("MyMessage", &s); upb_msgdef_addfield(m, newfield("field1", 1, UPB_TYPE_ENUM, UPB_LABEL_OPTIONAL, ".MyEnum", &s), &s, NULL); m2 = upb_msgdef_newnamed("MyMessage2", &s); e = upb_enumdef_newnamed("MyEnum", &s); ASSERT_STATUS(upb_enumdef_addval(e, "VAL1", 1, &status), &status); newdefs[0] = upb_msgdef_upcast_mutable(m); newdefs[1] = upb_msgdef_upcast_mutable(m2); newdefs[2] = upb_enumdef_upcast_mutable(e); ASSERT_STATUS(upb_symtab_add(s, newdefs, 3, &s, &status), &status); /* Try adding a new definition of MyEnum, MyMessage should get replaced with * a new version. */ e2 = upb_enumdef_newnamed("MyEnum", &s); ASSERT_STATUS(upb_enumdef_addval(e2, "VAL1", 1, &status), &status); newdefs2[0] = upb_enumdef_upcast_mutable(e2); ASSERT_STATUS(upb_symtab_add(s, newdefs2, 1, &s, &status), &status); m3 = upb_symtab_lookupmsg(s, "MyMessage"); ASSERT(m3); /* Must be different because it points to MyEnum which was replaced. */ ASSERT(m3 != m); m3 = upb_symtab_lookupmsg(s, "MyMessage2"); /* Should be the same because it was not replaced, nor were any defs that * are reachable from it. */ ASSERT(m3 == m2); upb_symtab_unref(s, &s); }
upb_enumdef *upb_enumdef_dup(const upb_enumdef *e, const void *owner) { upb_enumdef *new_e = upb_enumdef_new(owner); if (!new_e) return NULL; upb_enum_iter i; for(upb_enum_begin(&i, e); !upb_enum_done(&i); upb_enum_next(&i)) { bool success = upb_enumdef_addval( new_e, upb_enum_iter_name(&i),upb_enum_iter_number(&i), NULL); if (!success) { upb_enumdef_unref(new_e, owner); return NULL; } } return new_e; }
static void enumval_endmsg(void *_r, upb_status *status) { upb_descreader *r = _r; if(!r->saw_number || !r->saw_name) { upb_status_seterrliteral(status, "Enum value missing name or number."); return; } upb_enumdef *e = upb_downcast_enumdef_mutable(upb_descreader_last(r)); if (upb_enumdef_numvals(e) == 0) { // The default value of an enum (in the absence of an explicit default) is // its first listed value. upb_enumdef_setdefault(e, r->number); } upb_enumdef_addval(e, r->name, r->number, status); free(r->name); r->name = NULL; }
static bool enumval_endmsg(void *closure, const void *hd, upb_status *status) { UPB_UNUSED(hd); upb_descreader *r = closure; if(!r->saw_number || !r->saw_name) { upb_status_seterrmsg(status, "Enum value missing name or number."); return false; } upb_enumdef *e = upb_downcast_enumdef_mutable(upb_descreader_last(r)); if (upb_enumdef_numvals(e) == 0) { // The default value of an enum (in the absence of an explicit default) is // its first listed value. upb_enumdef_setdefault(e, r->number); } upb_enumdef_addval(e, r->name, r->number, status); free(r->name); r->name = NULL; return true; }