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; }
/* * call-seq: * Message.method_missing(*args) * * Provides accessors and setters for message fields according to their field * names. For any field whose name does not conflict with a built-in method, an * accessor is provided with the same name as the field, and a setter is * provided with the name of the field plus the '=' suffix. Thus, given a * message instance 'msg' with field 'foo', the following code is valid: * * msg.foo = 42 * puts msg.foo * * This method also provides read-only accessors for oneofs. If a oneof exists * with name 'my_oneof', then msg.my_oneof will return a Ruby symbol equal to * the name of the field in that oneof that is currently set, or nil if none. */ VALUE Message_method_missing(int argc, VALUE* argv, VALUE _self) { MessageHeader* self; VALUE method_name, method_str; char* name; size_t name_len; bool setter; const upb_oneofdef* o; const upb_fielddef* f; TypedData_Get_Struct(_self, MessageHeader, &Message_type, self); if (argc < 1) { rb_raise(rb_eArgError, "Expected method name as first argument."); } method_name = argv[0]; if (!SYMBOL_P(method_name)) { rb_raise(rb_eArgError, "Expected symbol as method name."); } method_str = rb_id2str(SYM2ID(method_name)); name = RSTRING_PTR(method_str); name_len = RSTRING_LEN(method_str); setter = false; // Setters have names that end in '='. if (name[name_len - 1] == '=') { setter = true; name_len--; } // Check for a oneof name first. o = upb_msgdef_ntoo(self->descriptor->msgdef, name, name_len); if (o != NULL) { if (setter) { rb_raise(rb_eRuntimeError, "Oneof accessors are read-only."); } return which_oneof_field(self, o); } // Otherwise, check for a field with that name. f = upb_msgdef_ntof(self->descriptor->msgdef, name, name_len); if (f == NULL) { return rb_call_super(argc, argv); } if (setter) { if (argc < 2) { rb_raise(rb_eArgError, "No value provided to setter."); } layout_set(self->descriptor->layout, Message_data(self), f, argv[1]); return Qnil; } else { return layout_get(self->descriptor->layout, Message_data(self), f); } }
static const upb_fielddef *lupb_msg_checkfield(lua_State *L, const lupb_msg *msg, int fieldarg) { size_t len; const char *fieldname = luaL_checklstring(L, fieldarg, &len); const upb_msgdef *msgdef = upb_msglayout_msgdef(msg->lmsgclass->layout); const upb_fielddef *f = upb_msgdef_ntof(msgdef, fieldname, len); if (!f) { const char *msg = lua_pushfstring(L, "no such field: %s", fieldname); luaL_argerror(L, fieldarg, msg); return NULL; /* Never reached. */ } return 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); }
upb_fielddef *upb_msgdef_ntof_mutable(upb_msgdef *m, const char *name) { return (upb_fielddef*)upb_msgdef_ntof(m, name); }
static const upb_fielddef *f(const upb_handlers *h, const char *name) { const upb_fielddef *ret = upb_msgdef_ntof(upb_handlers_msgdef(h), name); assert(ret); return ret; }