static void test_symbol_resolution() { upb_status s = UPB_STATUS_INIT; upb_def *defs[2]; upb_msgdef *m1; upb_msgdef *m2; upb_msgdef *m3; upb_fielddef *m3_field1; upb_fielddef *m3_field2; upb_symtab *symtab = upb_symtab_new(&symtab); ASSERT(symtab); /* m1 has name "A.B.C" and no fields. We'll add it to the symtab now. */ m1 = upb_msgdef_new(&m1); ASSERT(m1); ASSERT_STATUS(upb_msgdef_setfullname(m1, "A.B.C", &s), &s); ASSERT_STATUS(upb_symtab_add(symtab, (upb_def**)&m1, 1, NULL, &s), &s); /* m2 has name "D.E" and no fields. We'll add it in the same batch as m3 * below. */ m2 = upb_msgdef_new(&m2); ASSERT(m2); ASSERT_STATUS(upb_msgdef_setfullname(m2, "D.E", &s), &s); /* m3 has name "F.G" and two fields, of type A.B.C and D.E respectively. We'll * add it in the same batch as m2 above. */ m3 = upb_msgdef_new(&m3); ASSERT(m3); ASSERT_STATUS(upb_msgdef_setfullname(m3, "F.G", &s), &s); m3_field1 = upb_fielddef_new(&m3_field1); ASSERT_STATUS(upb_fielddef_setname(m3_field1, "field1", &s), &s); ASSERT_STATUS(upb_fielddef_setnumber(m3_field1, 1, &s), &s); upb_fielddef_setlabel(m3_field1, UPB_LABEL_OPTIONAL); upb_fielddef_settype(m3_field1, UPB_TYPE_MESSAGE); ASSERT_STATUS(upb_fielddef_setsubdefname(m3_field1, ".A.B.C", &s), &s); ASSERT_STATUS(upb_msgdef_addfield(m3, m3_field1, NULL, &s), &s); m3_field2 = upb_fielddef_new(&m3_field2); ASSERT_STATUS(upb_fielddef_setname(m3_field2, "field2", &s), &s); ASSERT_STATUS(upb_fielddef_setnumber(m3_field2, 2, &s), &s); upb_fielddef_setlabel(m3_field2, UPB_LABEL_OPTIONAL); upb_fielddef_settype(m3_field2, UPB_TYPE_MESSAGE); ASSERT_STATUS(upb_fielddef_setsubdefname(m3_field2, ".D.E", &s), &s); ASSERT_STATUS(upb_msgdef_addfield(m3, m3_field2, NULL, &s), &s); defs[0] = upb_msgdef_upcast_mutable(m2); defs[1] = upb_msgdef_upcast_mutable(m3); ASSERT_STATUS(upb_symtab_add(symtab, defs, 2, NULL, &s), &s); upb_fielddef_unref(m3_field2, &m3_field2); upb_fielddef_unref(m3_field1, &m3_field1); upb_msgdef_unref(m3, &m3); upb_msgdef_unref(m2, &m2); upb_msgdef_unref(m1, &m1); upb_symtab_unref(symtab, &symtab); }
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), NULL); upb_fielddef_setname(newf, upb_fielddef_name(f), NULL); if (f->default_is_string) { str_t *s = upb_value_getptr(upb_fielddef_default(f)); upb_fielddef_setdefaultstr(newf, s->str, s->len, NULL); } 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, NULL); free(newname); } return newf; }
static void test_fielddef() { /* Test that we don't leak an unresolved subdef name. */ upb_fielddef *f1 = upb_fielddef_new(&f1); upb_fielddef_settype(f1, UPB_TYPE_MESSAGE); ASSERT(upb_fielddef_setsubdefname(f1, "YO", NULL)); upb_fielddef_unref(f1, &f1); }
bool upb_msgdef_addfields(upb_msgdef *m, upb_fielddef *const *fields, int n, const void *ref_donor, upb_status *s) { // Check constraints for all fields before performing any action. for (int i = 0; i < n; i++) { upb_fielddef *f = fields[i]; // TODO(haberman): handle the case where two fields of the input duplicate // name or number. if (f->msgdef != NULL) { upb_status_seterrliteral(s, "fielddef already belongs to a message"); return false; } else if (upb_fielddef_name(f) == NULL || upb_fielddef_number(f) == 0) { upb_status_seterrliteral(s, "field name or number were not set"); return false; } else if(upb_msgdef_itof(m, upb_fielddef_number(f)) || upb_msgdef_ntof(m, upb_fielddef_name(f))) { upb_status_seterrliteral(s, "duplicate field name or number"); return false; } } // Constraint checks ok, perform the action. for (int i = 0; i < n; i++) { upb_fielddef *f = fields[i]; f->msgdef = m; upb_inttable_insert(&m->itof, upb_fielddef_number(f), upb_value_ptr(f)); upb_strtable_insert(&m->ntof, upb_fielddef_name(f), upb_value_ptr(f)); upb_ref2(f, m); upb_ref2(m, f); if (ref_donor) upb_fielddef_unref(f, ref_donor); } return true; }
bool upb_msgdef_addfields(upb_msgdef *m, upb_fielddef *const *fields, int n, const void *ref_donor) { // Check constraints for all fields before performing any action. for (int i = 0; i < n; i++) { upb_fielddef *f = fields[i]; // TODO(haberman): handle the case where two fields of the input duplicate // name or number. if (f->msgdef != NULL || upb_fielddef_name(f) == NULL || upb_fielddef_number(f) == 0 || upb_msgdef_itof(m, upb_fielddef_number(f)) || upb_msgdef_ntof(m, upb_fielddef_name(f))) return false; } // Constraint checks ok, perform the action. for (int i = 0; i < n; i++) { upb_fielddef *f = fields[i]; f->msgdef = m; upb_inttable_insert(&m->itof, upb_fielddef_number(f), upb_value_ptr(f)); upb_strtable_insert(&m->ntof, upb_fielddef_name(f), upb_value_ptr(f)); upb_ref2(f, m); upb_ref2(m, f); if (ref_donor) upb_fielddef_unref(f, ref_donor); } return true; }
static bool discardfield(void *_r, void *fval) { UPB_UNUSED(fval); upb_descreader *r = _r; // Discard extension field so we don't leak it. upb_fielddef_unref(r->f, &r->defs); r->f = NULL; return true; }
static void test_fielddef_unref() { bool ok; upb_symtab *s = load_test_proto(&s); const upb_msgdef *md = upb_symtab_lookupmsg(s, "A"); const upb_fielddef *f = upb_msgdef_itof(md, 1); upb_fielddef_ref(f, &f); /* Unref symtab; now fielddef is the only thing keeping the msgdef alive. */ upb_symtab_unref(s, &s); /* Check that md is still alive. */ ok = strcmp(upb_msgdef_fullname(md), "A") == 0; ASSERT(ok); /* Check that unref of fielddef frees the whole remaining graph. */ upb_fielddef_unref(f, &f); }
bool upb_msgdef_addfields(upb_msgdef *m, upb_fielddef *const *fields, int n, const void *ref_donor, upb_status *s) { // TODO: extensions need to have a separate namespace, because proto2 allows a // top-level extension (ie. one not in any package) to have the same name as a // field from the message. // // This also implies that there needs to be a separate lookup-by-name method // for extensions. It seems desirable for iteration to return both extensions // and non-extensions though. // // We also need to validate that the field number is in an extension range iff // it is an extension. // Check constraints for all fields before performing any action. for (int i = 0; i < n; i++) { upb_fielddef *f = fields[i]; // TODO(haberman): handle the case where two fields of the input duplicate // name or number. if (upb_fielddef_containingtype(f) != NULL) { upb_status_seterrmsg(s, "fielddef already belongs to a message"); return false; } else if (upb_fielddef_name(f) == NULL || upb_fielddef_number(f) == 0) { upb_status_seterrmsg(s, "field name or number were not set"); return false; } else if(upb_msgdef_itof(m, upb_fielddef_number(f)) || upb_msgdef_ntof(m, upb_fielddef_name(f))) { upb_status_seterrmsg(s, "duplicate field name or number"); return false; } } // Constraint checks ok, perform the action. for (int i = 0; i < n; i++) { upb_fielddef *f = fields[i]; release_containingtype(f); f->msg.def = m; f->msg_is_symbolic = false; upb_inttable_insert(&m->itof, upb_fielddef_number(f), upb_value_ptr(f)); upb_strtable_insert(&m->ntof, upb_fielddef_name(f), upb_value_ptr(f)); upb_ref2(f, m); upb_ref2(m, f); if (ref_donor) upb_fielddef_unref(f, ref_donor); } 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; }
static void PyUpb_FieldDef_dealloc(PyObject *obj) { PyUpb_ObjWrapper *wrapper = (void*)obj; if (wrapper->weakreflist) PyObject_ClearWeakRefs(obj); upb_fielddef_unref((upb_fielddef*)wrapper->obj); obj->ob_type->tp_free(obj); }
void FieldDescriptor_free(void* _self) { FieldDescriptor* self = _self; upb_fielddef_unref(self->fielddef, &self->fielddef); xfree(self); }