/** * lupb_map_typecheck() * * Checks that the lupb_map at index |narg| can be safely assigned to the * field |f| of the message at index |msg|. If so, returns a upb_msgval for * this map. Otherwise, raises a Lua error. */ static upb_msgval lupb_map_typecheck(lua_State *L, int narg, int msg, const upb_fielddef *f) { lupb_map *lmap = lupb_map_check(L, narg); upb_map *map = lmap->map; const upb_msgdef *entry = upb_fielddef_msgsubdef(f); const upb_fielddef *key_field = upb_msgdef_itof(entry, UPB_MAPENTRY_KEY); const upb_fielddef *value_field = upb_msgdef_itof(entry, UPB_MAPENTRY_VALUE); UPB_ASSERT(entry && key_field && value_field); if (upb_map_keytype(map) != upb_fielddef_type(key_field)) { luaL_error(L, "Map key type invalid"); } if (upb_map_valuetype(map) != upb_fielddef_type(value_field)) { luaL_error(L, "Map had incorrect value type (expected: %s, got: %s)", upb_fielddef_type(value_field), upb_map_valuetype(map)); } if (upb_map_valuetype(map) == UPB_TYPE_MESSAGE) { lupb_msgclass_typecheck( L, lupb_msg_msgclassfor(L, msg, upb_fielddef_msgsubdef(value_field)), lmap->value_lmsgclass); } return upb_msgval_map(map); }
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; }
// Allocates a new map_handlerdata_t given the map entry message definition. If // the offset of the field within the parent message is also given, that is // added to the handler data as well. Note that this is called *twice* per map // field: once in the parent message handler setup when setting the startsubmsg // handler and once in the map entry message handler setup when setting the // key/value and endmsg handlers. The reason is that there is no easy way to // pass the handlerdata down to the sub-message handler setup. static map_handlerdata_t* new_map_handlerdata( size_t ofs, const upb_msgdef* mapentry_def, Descriptor* desc) { const upb_fielddef* key_field; const upb_fielddef* value_field; map_handlerdata_t* hd = ALLOC(map_handlerdata_t); hd->ofs = ofs; key_field = upb_msgdef_itof(mapentry_def, MAP_KEY_FIELD); assert(key_field != NULL); hd->key_field_type = upb_fielddef_type(key_field); value_field = upb_msgdef_itof(mapentry_def, MAP_VALUE_FIELD); assert(value_field != NULL); hd->value_field_type = upb_fielddef_type(value_field); hd->value_field_subdef = upb_fielddef_subdef(value_field); return hd; }
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; }
bool upb_msgdef_addfields(upb_msgdef *m, upb_fielddef *const *fields, int n) { // Check constraints for all fields before performing any action. for (int i = 0; i < n; i++) { upb_fielddef *f = fields[i]; assert(upb_atomic_read(&f->refcount) > 0); if (f->name == NULL || f->number == 0 || upb_msgdef_itof(m, f->number) || upb_msgdef_ntof(m, f->name)) return false; } // Constraint checks ok, perform the action. for (int i = 0; i < n; i++) { upb_fielddef *f = fields[i]; upb_msgdef_ref(m); assert(f->msgdef == NULL); f->msgdef = m; upb_itof_ent itof_ent = {0, f}; upb_inttable_insert(&m->itof, f->number, &itof_ent); upb_strtable_insert(&m->ntof, f->name, &f); } return true; }
static void test_cycles() { bool ok; upb_symtab *s = load_test_proto(&s); const upb_msgdef *m; const upb_fielddef *f; const upb_def *def; const upb_def *def2; /* Test cycle detection by making a cyclic def's main refcount go to zero * and then be incremented to one again. */ def = upb_symtab_lookup(s, "A"); upb_def_ref(def, &def); ASSERT(def); ASSERT(upb_def_isfrozen(def)); upb_symtab_unref(s, &s); /* Message A has only one subfield: "optional B b = 1". */ m = upb_downcast_msgdef(def); f = upb_msgdef_itof(m, 1); ASSERT(f); ASSERT(upb_fielddef_hassubdef(f)); ASSERT(upb_msgdef_ntofz(m, "b") == f); ASSERT(upb_msgdef_ntof(m, "b", 1) == f); def2 = upb_fielddef_subdef(f); ASSERT(upb_downcast_msgdef(def2)); ok = strcmp(upb_def_fullname(def2), "B") == 0; ASSERT(ok); upb_def_ref(def2, &def2); upb_def_unref(def, &def); /* We know "def" is still alive because it's reachable from def2. */ ok = strcmp(upb_def_fullname(def), "A") == 0; ASSERT(ok); upb_def_unref(def2, &def2); }
const upb_fielddef* map_entry_value(const upb_msgdef* msgdef) { const upb_fielddef* value_field = upb_msgdef_itof(msgdef, MAP_VALUE_FIELD); assert(value_field != NULL); return value_field; }
const upb_fielddef* map_entry_key(const upb_msgdef* msgdef) { const upb_fielddef* key_field = upb_msgdef_itof(msgdef, MAP_KEY_FIELD); assert(key_field != NULL); return key_field; }
upb_fielddef *upb_msgdef_itof_mutable(upb_msgdef *m, uint32_t i) { return (upb_fielddef*)upb_msgdef_itof(m, i); }