Beispiel #1
0
// TODO(haberman): discard upb_handlers* objects that do not actually have any
// handlers set and cannot reach any upb_handlers* object that does.  This is
// slightly tricky to do correctly.
static upb_handlers *newformsg(const upb_msgdef *m, const void *owner,
                               dfs_state *s) {
  upb_handlers *h = upb_handlers_new(m, owner);
  if (!h) return NULL;
  if (!upb_inttable_insertptr(&s->tab, m, upb_value_ptr(h))) goto oom;

  s->callback(s->closure, h);

  // For each submessage field, get or create a handlers object and set it as
  // the subhandlers.
  upb_msg_iter i;
  for(upb_msg_begin(&i, m); !upb_msg_done(&i); upb_msg_next(&i)) {
    upb_fielddef *f = upb_msg_iter_field(&i);
    if (!upb_fielddef_issubmsg(f)) continue;

    const upb_msgdef *subdef = upb_downcast_msgdef(upb_fielddef_subdef(f));
    upb_value subm_ent;
    if (upb_inttable_lookupptr(&s->tab, subdef, &subm_ent)) {
      upb_handlers_setsubhandlers(h, f, upb_value_getptr(subm_ent));
    } else {
      upb_handlers *sub_mh = newformsg(subdef, &sub_mh, s);
      if (!sub_mh) goto oom;
      upb_handlers_setsubhandlers(h, f, sub_mh);
      upb_handlers_unref(sub_mh, &sub_mh);
    }
  }
  return h;

oom:
  upb_handlers_unref(h, owner);
  return NULL;
}
Beispiel #2
0
void layout_deep_copy(MessageLayout* layout, void* to, void* from) {
  upb_msg_field_iter it;
  for (upb_msg_field_begin(&it, layout->msgdef);
       !upb_msg_field_done(&it);
       upb_msg_field_next(&it)) {
    const upb_fielddef* field = upb_msg_iter_field(&it);

    void* to_memory = slot_memory(layout, to, field);
    uint32_t* to_oneof_case = slot_oneof_case(layout, to, field);
    void* from_memory = slot_memory(layout, from, field);
    uint32_t* from_oneof_case = slot_oneof_case(layout, from, field);

    if (upb_fielddef_containingoneof(field)) {
      if (*from_oneof_case == upb_fielddef_number(field)) {
        *to_oneof_case = *from_oneof_case;
        native_slot_deep_copy(upb_fielddef_type(field), to_memory, from_memory);
      }
    } else if (is_map_field(field)) {
      DEREF(to_memory, VALUE) =
          Map_deep_copy(DEREF(from_memory, VALUE));
    } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
      DEREF(to_memory, VALUE) =
          RepeatedField_deep_copy(DEREF(from_memory, VALUE));
    } else {
      if (field_contains_hasbit(layout, field)) {
        if (!slot_is_hasbit_set(layout, from, field)) continue;
        slot_set_hasbit(layout, to, field);
      }

      native_slot_deep_copy(upb_fielddef_type(field), to_memory, from_memory);
    }
  }
}
Beispiel #3
0
bool upb_symtab_dfs(upb_def *def, upb_def **open_defs, int n,
                    upb_strtable *addtab) {
  // This linear search makes the DFS O(n^2) in the length of the paths.
  // Could make this O(n) with a hash table, but n is small.
  for (int i = 0; i < n; i++) {
    if (def == open_defs[i]) return false;
  }

  bool needcopy = false;
  upb_msgdef *m = upb_dyncast_msgdef(def);
  if (m) {
    upb_msg_iter i;
    open_defs[n++] = def;
    for(i = upb_msg_begin(m); !upb_msg_done(i); i = upb_msg_next(m, i)) {
      upb_fielddef *f = upb_msg_iter_field(i);
      if (!upb_hassubdef(f)) continue;
      needcopy |= upb_symtab_dfs(f->def, open_defs, n, addtab);
    }
  }

  bool replacing = (upb_strtable_lookup(addtab, m->base.fqname) != NULL);
  if (needcopy && !replacing) {
    upb_symtab_ent e = {upb_def_dup(def)};
    upb_strtable_insert(addtab, def->fqname, &e);
    replacing = true;
  }
  return replacing;
}
Beispiel #4
0
// narg is a lua table containing a list of defs to add.
static PyObject *PyUpb_SymbolTable_add_defs(PyObject *o, PyObject *defs) {
  upb_symtab *s = Check_SymbolTable(o, NULL);
  if (!PySequence_Check(defs)) return PyUpb_Error("Must be a sequence");
  Py_ssize_t n = PySequence_Length(defs);

  // Prevent stack overflow.
  if (n > 2048) return PyUpb_Error("Too many defs");
  upb_def *cdefs[n];

  int i = 0;
  for (i = 0; i < n; i++) {
    PyObject *pydef = PySequence_GetItem(defs, i);
    upb_def *def = Check_MessageDef(pydef, NULL);
    cdefs[i++] = def;
    upb_msgdef *md = upb_dyncast_msgdef(def);
    if (!md) continue;
    upb_msg_field_iter j;
    for(upb_msg_field_begin(&j, md);
        !upb_msg_field_done(&j);
        upb_msg_field_next(&j)) {
      upb_fielddef *f = upb_msg_iter_field(j);
      upb_fielddef_setaccessor(f, PyUpb_AccessorForField(f));
    }
    upb_msgdef_layout(md);
  }

  upb_status status = UPB_STATUS_INIT;
  upb_symtab_add(s, cdefs, n, &status);
  PyUpb_CheckStatus(&status);
  return Py_None;
}
Beispiel #5
0
void layout_init(MessageLayout* layout,
                 void* storage) {
    upb_msg_field_iter it;
    for (upb_msg_field_begin(&it, layout->msgdef);
            !upb_msg_field_done(&it);
            upb_msg_field_next(&it)) {
        const upb_fielddef* field = upb_msg_iter_field(&it);
        void* memory = slot_memory(layout, storage, field);
        uint32_t* oneof_case = slot_oneof_case(layout, storage, field);

        if (upb_fielddef_containingoneof(field)) {
            memset(memory, 0, NATIVE_SLOT_MAX_SIZE);
            *oneof_case = ONEOF_CASE_NONE;
        } else if (is_map_field(field)) {
            VALUE map = Qnil;

            const upb_fielddef* key_field = map_field_key(field);
            const upb_fielddef* value_field = map_field_value(field);
            VALUE type_class = field_type_class(value_field);

            if (type_class != Qnil) {
                VALUE args[3] = {
                    fieldtype_to_ruby(upb_fielddef_type(key_field)),
                    fieldtype_to_ruby(upb_fielddef_type(value_field)),
                    type_class,
                };
                map = rb_class_new_instance(3, args, cMap);
            } else {
                VALUE args[2] = {
                    fieldtype_to_ruby(upb_fielddef_type(key_field)),
                    fieldtype_to_ruby(upb_fielddef_type(value_field)),
                };
                map = rb_class_new_instance(2, args, cMap);
            }

            DEREF(memory, VALUE) = map;
        } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
            VALUE ary = Qnil;

            VALUE type_class = field_type_class(field);

            if (type_class != Qnil) {
                VALUE args[2] = {
                    fieldtype_to_ruby(upb_fielddef_type(field)),
                    type_class,
                };
                ary = rb_class_new_instance(2, args, cRepeatedField);
            } else {
                VALUE args[1] = { fieldtype_to_ruby(upb_fielddef_type(field)) };
                ary = rb_class_new_instance(1, args, cRepeatedField);
            }

            DEREF(memory, VALUE) = ary;
        } else {
            native_slot_init(upb_fielddef_type(field), memory);
        }
    }
}
Beispiel #6
0
static void onmreg(const void *c, upb_handlers *h) {
  const upb_msgdef *m = upb_handlers_msgdef(h);
  upb_msg_field_iter i;
  UPB_UNUSED(c);

  upb_handlers_setstartmsg(h, textprinter_startmsg, NULL);
  upb_handlers_setendmsg(h, textprinter_endmsg, NULL);

  for(upb_msg_field_begin(&i, m);
      !upb_msg_field_done(&i);
      upb_msg_field_next(&i)) {
    upb_fielddef *f = upb_msg_iter_field(&i);
    upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
    upb_handlerattr_sethandlerdata(&attr, f);
    switch (upb_fielddef_type(f)) {
      case UPB_TYPE_INT32:
        upb_handlers_setint32(h, f, textprinter_putint32, &attr);
        break;
      case UPB_TYPE_INT64:
        upb_handlers_setint64(h, f, textprinter_putint64, &attr);
        break;
      case UPB_TYPE_UINT32:
        upb_handlers_setuint32(h, f, textprinter_putuint32, &attr);
        break;
      case UPB_TYPE_UINT64:
        upb_handlers_setuint64(h, f, textprinter_putuint64, &attr);
        break;
      case UPB_TYPE_FLOAT:
        upb_handlers_setfloat(h, f, textprinter_putfloat, &attr);
        break;
      case UPB_TYPE_DOUBLE:
        upb_handlers_setdouble(h, f, textprinter_putdouble, &attr);
        break;
      case UPB_TYPE_BOOL:
        upb_handlers_setbool(h, f, textprinter_putbool, &attr);
        break;
      case UPB_TYPE_STRING:
      case UPB_TYPE_BYTES:
        upb_handlers_setstartstr(h, f, textprinter_startstr, &attr);
        upb_handlers_setstring(h, f, textprinter_putstr, &attr);
        upb_handlers_setendstr(h, f, textprinter_endstr, &attr);
        break;
      case UPB_TYPE_MESSAGE: {
        const char *name =
            upb_fielddef_istagdelim(f)
                ? shortname(upb_msgdef_fullname(upb_fielddef_msgsubdef(f)))
                : upb_fielddef_name(f);
        upb_handlerattr_sethandlerdata(&attr, name);
        upb_handlers_setstartsubmsg(h, f, textprinter_startsubmsg, &attr);
        upb_handlers_setendsubmsg(h, f, textprinter_endsubmsg, &attr);
        break;
      }
      case UPB_TYPE_ENUM:
        upb_handlers_setint32(h, f, textprinter_putenum, &attr);
        break;
    }
  }
}
Beispiel #7
0
Datei: def.c Projekt: Phuehvk/upb
static void visitmsg(const upb_refcounted *r, upb_refcounted_visit *visit,
                     void *closure) {
  const upb_msgdef *m = (const upb_msgdef*)r;
  upb_msg_iter i;
  for(upb_msg_begin(&i, m); !upb_msg_done(&i); upb_msg_next(&i)) {
    upb_fielddef *f = upb_msg_iter_field(&i);
    visit(r, upb_upcast2(f), closure);
  }
}
Beispiel #8
0
static void upb_msgdef_free(upb_msgdef *m) {
  upb_msg_iter i;
  for(i = upb_msg_begin(m); !upb_msg_done(i); i = upb_msg_next(m, i))
    upb_fielddef_free(upb_msg_iter_field(i));
  upb_strtable_free(&m->ntof);
  upb_inttable_free(&m->itof);
  upb_def_uninit(&m->base);
  free(m);
}
Beispiel #9
0
void layout_init(MessageLayout* layout,
                 void* storage) {

  upb_msg_field_iter it;
  for (upb_msg_field_begin(&it, layout->msgdef);
       !upb_msg_field_done(&it);
       upb_msg_field_next(&it)) {
    layout_clear(layout, storage, upb_msg_iter_field(&it));
  }
}
Beispiel #10
0
static void validate_msgdef(const upb_msgdef* msgdef) {
  // Verify that no required fields exist. proto3 does not support these.
  upb_msg_iter it;
  for (upb_msg_begin(&it, msgdef); !upb_msg_done(&it); upb_msg_next(&it)) {
    const upb_fielddef* field = upb_msg_iter_field(&it);
    if (upb_fielddef_label(field) == UPB_LABEL_REQUIRED) {
      rb_raise(rb_eTypeError, "Required fields are unsupported in proto3.");
    }
  }
}
Beispiel #11
0
static void visithandlers(const upb_refcounted *r, upb_refcounted_visit *visit,
                          void *closure) {
  const upb_handlers *h = (const upb_handlers*)r;
  upb_msg_iter i;
  for(upb_msg_begin(&i, h->msg); !upb_msg_done(&i); upb_msg_next(&i)) {
    upb_fielddef *f = upb_msg_iter_field(&i);
    if (!upb_fielddef_issubmsg(f)) continue;
    const upb_handlers *sub = upb_handlers_getsubhandlers(h, f);
    if (sub) visit(r, UPB_UPCAST(sub), closure);
  }
}
Beispiel #12
0
upb_msgdef *upb_msgdef_dup(const upb_msgdef *m) {
  upb_msgdef *newm = upb_msgdef_new();
  newm->size = m->size;
  newm->hasbit_bytes = m->hasbit_bytes;
  newm->extstart = m->extstart;
  newm->extend = m->extend;
  upb_msg_iter i;
  for(i = upb_msg_begin(m); !upb_msg_done(i); i = upb_msg_next(m, i)) {
    upb_msgdef_addfield(newm, upb_fielddef_dup(upb_msg_iter_field(i)));
  }
  return newm;
}
Beispiel #13
0
static PyObject *PyUpb_MessageDef_fields(PyObject *obj, PyObject *args) {
  upb_msgdef *m = Check_MessageDef(obj, NULL);
  PyObject *ret = PyList_New(0);
  upb_msg_field_iter i;
  for(upb_msg_field_begin(&i, m);
      !upb_msg_field_done(&i);
      upb_msg_field_next(&ii)) {
    upb_fielddef *f = upb_msg_iter_field(&i);
    PyList_Append(ret, PyUpb_FieldDef_GetOrCreate(f));
  }
  return ret;
}
Beispiel #14
0
/*
 * call-seq:
 *     Descriptor.each(&block)
 *
 * Iterates over fields in this message type, yielding to the block on each one.
 */
VALUE Descriptor_each(VALUE _self) {
  DEFINE_SELF(Descriptor, self, _self);

  upb_msg_iter it;
  for (upb_msg_begin(&it, self->msgdef);
       !upb_msg_done(&it);
       upb_msg_next(&it)) {
    const upb_fielddef* field = upb_msg_iter_field(&it);
    VALUE obj = get_def_obj(field);
    rb_yield(obj);
  }
  return Qnil;
}
Beispiel #15
0
upb_msgdef *upb_msgdef_dup(const upb_msgdef *m, const void *owner) {
  upb_msgdef *newm = upb_msgdef_new(owner);
  if (!newm) return NULL;
  upb_def_setfullname(upb_upcast(newm), upb_def_fullname(upb_upcast(m)));
  upb_msg_iter i;
  for(upb_msg_begin(&i, m); !upb_msg_done(&i); upb_msg_next(&i)) {
    upb_fielddef *f = upb_fielddef_dup(upb_msg_iter_field(&i), &f);
    if (!f || !upb_msgdef_addfield(newm, f, &f)) {
      upb_msgdef_unref(newm, owner);
      return NULL;
    }
  }
  return newm;
}
Beispiel #16
0
VALUE layout_hash(MessageLayout* layout, void* storage) {
  upb_msg_field_iter it;
  st_index_t h = rb_hash_start(0);
  VALUE hash_sym = rb_intern("hash");
  for (upb_msg_field_begin(&it, layout->msgdef);
       !upb_msg_field_done(&it);
       upb_msg_field_next(&it)) {
    const upb_fielddef* field = upb_msg_iter_field(&it);
    VALUE field_val = layout_get(layout, storage, field);
    h = rb_hash_uint(h, NUM2LONG(rb_funcall(field_val, hash_sym, 0)));
  }
  h = rb_hash_end(h);

  return INT2FIX(h);
}
Beispiel #17
0
Datei: def.c Projekt: Phuehvk/upb
bool upb_def_freeze(upb_def *const* defs, int n, upb_status *s) {
  // First perform validation, in two passes so we can check that we have a
  // transitive closure without needing to search.
  for (int i = 0; i < n; i++) {
    upb_def *def = defs[i];
    if (upb_def_isfrozen(def)) {
      // Could relax this requirement if it's annoying.
      upb_status_seterrliteral(s, "def is already frozen");
      goto err;
    } else if (def->type == UPB_DEF_FIELD) {
      upb_status_seterrliteral(s, "standalone fielddefs can not be frozen");
      goto err;
    } else {
      // Set now to detect transitive closure in the second pass.
      def->came_from_user = true;
    }
  }

  for (int i = 0; i < n; i++) {
    upb_msgdef *m = upb_dyncast_msgdef_mutable(defs[i]);
    upb_enumdef *e = upb_dyncast_enumdef_mutable(defs[i]);
    if (m) {
      upb_inttable_compact(&m->itof);
      upb_msg_iter j;
      uint32_t selector = UPB_STATIC_SELECTOR_COUNT;
      for(upb_msg_begin(&j, m); !upb_msg_done(&j); upb_msg_next(&j)) {
        upb_fielddef *f = upb_msg_iter_field(&j);
        assert(f->msgdef == m);
        if (!upb_validate_field(f, s)) goto err;
        f->selector_base = selector + upb_handlers_selectorbaseoffset(f);
        selector += upb_handlers_selectorcount(f);
      }
      m->selector_count = selector;
    } else if (e) {
      upb_inttable_compact(&e->iton);
    }
  }

  // Validation all passed; freeze the defs.
  return upb_refcounted_freeze((upb_refcounted*const*)defs, n, s);

err:
  for (int i = 0; i < n; i++) {
    defs[i]->came_from_user = false;
  }
  assert(!upb_ok(s));
  return false;
}
Beispiel #18
0
Datei: def.c Projekt: YauzZ/upb
upb_msgdef *upb_msgdef_dup(const upb_msgdef *m, const void *owner) {
  upb_msgdef *newm = upb_msgdef_new(owner);
  if (!newm) return NULL;
  bool ok = upb_def_setfullname(UPB_UPCAST(newm),
                                upb_def_fullname(UPB_UPCAST(m)), NULL);
  UPB_ASSERT_VAR(ok, ok);
  upb_msg_iter i;
  for(upb_msg_begin(&i, m); !upb_msg_done(&i); upb_msg_next(&i)) {
    upb_fielddef *f = upb_fielddef_dup(upb_msg_iter_field(&i), &f);
    if (!f || !upb_msgdef_addfield(newm, f, &f, NULL)) {
      upb_msgdef_unref(newm, owner);
      return NULL;
    }
  }
  return newm;
}
Beispiel #19
0
/*
 * call-seq:
 *     Message.to_h => {}
 *
 * Returns the message as a Ruby Hash object, with keys as symbols.
 */
VALUE Message_to_h(VALUE _self) {
  MessageHeader* self;
  VALUE hash;
  upb_msg_field_iter it;
  TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);

  hash = rb_hash_new();

  for (upb_msg_field_begin(&it, self->descriptor->msgdef);
       !upb_msg_field_done(&it);
       upb_msg_field_next(&it)) {
    const upb_fielddef* field = upb_msg_iter_field(&it);

    // For proto2, do not include fields which are not set.
    if (upb_msgdef_syntax(self->descriptor->msgdef) == UPB_SYNTAX_PROTO2 &&
	field_contains_hasbit(self->descriptor->layout, field) &&
	!layout_has(self->descriptor->layout, Message_data(self), field)) {
      continue;
    }

    VALUE msg_value = layout_get(self->descriptor->layout, Message_data(self),
                                 field);
    VALUE msg_key   = ID2SYM(rb_intern(upb_fielddef_name(field)));
    if (is_map_field(field)) {
      msg_value = Map_to_h(msg_value);
    } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
      msg_value = RepeatedField_to_ary(msg_value);
      if (upb_msgdef_syntax(self->descriptor->msgdef) == UPB_SYNTAX_PROTO2 &&
          RARRAY_LEN(msg_value) == 0) {
        continue;
      }

      if (upb_fielddef_type(field) == UPB_TYPE_MESSAGE) {
        for (int i = 0; i < RARRAY_LEN(msg_value); i++) {
          VALUE elem = rb_ary_entry(msg_value, i);
          rb_ary_store(msg_value, i, Message_to_h(elem));
        }
      }

    } else if (msg_value != Qnil &&
               upb_fielddef_type(field) == UPB_TYPE_MESSAGE) {
      msg_value = Message_to_h(msg_value);
    }
    rb_hash_aset(hash, msg_key, msg_value);
  }
  return hash;
}
Beispiel #20
0
void upb_msgdef_layout(upb_msgdef *m) {
  // Create an ordering over the fields, but only include fields with accessors.
  upb_fielddef **sorted_fields =
      malloc(sizeof(upb_fielddef*) * upb_msgdef_numfields(m));
  int n = 0;
  upb_msg_iter i;
  for (i = upb_msg_begin(m); !upb_msg_done(i); i = upb_msg_next(m, i)) {
    upb_fielddef *f = upb_msg_iter_field(i);
    if (f->accessor) sorted_fields[n++] = f;
  }

  m->hasbit_bytes = upb_div_round_up(n, 8);
  m->size = m->hasbit_bytes;  // + header_size?

  // Assign hasbits.
  qsort(sorted_fields, n, sizeof(*sorted_fields), upb_fielddef_cmphasbit);
  for (int i = 0; i < n; i++) {
    upb_fielddef *f = sorted_fields[i];
    f->hasbit = i;
  }

  // Assign value offsets.
  qsort(sorted_fields, n, sizeof(*sorted_fields), upb_fielddef_cmpval);
  size_t max_align = 0;
  for (int i = 0; i < n; i++) {
    upb_fielddef *f = sorted_fields[i];
    const upb_type_info *type_info = &upb_types[f->type];
    size_t size = type_info->size;
    size_t align = type_info->align;
    if (upb_isseq(f)) {
      size = sizeof(void*);
      align = alignof(void*);
    }

    // General alignment rules are: each member must be at an address that is a
    // multiple of that type's alignment.  Also, the size of the structure as a
    // whole must be a multiple of the greatest alignment of any member.
    f->offset = upb_align_up(m->size, align);
    m->size = f->offset + size;
    max_align = UPB_MAX(max_align, align);
  }
  if (max_align > 0) m->size = upb_align_up(m->size, max_align);

  free(sorted_fields);
}
Beispiel #21
0
static upb_flow_t upb_msg_dispatch(upb_msg *msg, upb_msgdef *md,
                                   upb_dispatcher *d) {
  upb_msg_iter i;
  for(i = upb_msg_begin(md); !upb_msg_done(i); i = upb_msg_next(md, i)) {
    upb_fielddef *f = upb_msg_iter_field(i);
    if (!upb_msg_has(msg, f)) continue;
    upb_fhandlers *hf = upb_dispatcher_lookup(d, f->number);
    if (!hf) continue;
    upb_value val = upb_msg_get(msg, f);
    if (upb_isarray(f)) {
      upb_array *arr = upb_value_getarr(val);
      for (uint32_t j = 0; j < upb_array_len(arr); ++j) {
        upb_msg_pushval(upb_array_get(arr, f, j), f, d, hf);
      }
    } else {
      upb_msg_pushval(val, f, d, hf);
    }
  }
  return UPB_CONTINUE;
}
Beispiel #22
0
VALUE Message_to_h(VALUE _self) {
  MessageHeader* self;
  TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);

  VALUE hash = rb_hash_new();

  upb_msg_field_iter it;
  for (upb_msg_field_begin(&it, self->descriptor->msgdef);
       !upb_msg_field_done(&it);
       upb_msg_field_next(&it)) {
    const upb_fielddef* field = upb_msg_iter_field(&it);
    VALUE msg_value = layout_get(self->descriptor->layout, Message_data(self), field);
    VALUE msg_key   = ID2SYM(rb_intern(upb_fielddef_name(field)));
    if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
      msg_value = RepeatedField_to_ary(msg_value);
    }
    rb_hash_aset(hash, msg_key, msg_value);
  }
  return hash;
}
Beispiel #23
0
void layout_mark(MessageLayout* layout, void* storage) {
  upb_msg_field_iter it;
  for (upb_msg_field_begin(&it, layout->msgdef);
       !upb_msg_field_done(&it);
       upb_msg_field_next(&it)) {
    const upb_fielddef* field = upb_msg_iter_field(&it);
    void* memory = slot_memory(layout, storage, field);
    uint32_t* oneof_case = slot_oneof_case(layout, storage, field);

    if (upb_fielddef_containingoneof(field)) {
      if (*oneof_case == upb_fielddef_number(field)) {
        native_slot_mark(upb_fielddef_type(field), memory);
      }
    } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
      rb_gc_mark(DEREF(memory, VALUE));
    } else {
      native_slot_mark(upb_fielddef_type(field), memory);
    }
  }
}
Beispiel #24
0
void upb_stdmsg_free(void *m, const upb_msgdef *md) {
  if (m == NULL) return;
  upb_msg_iter i;
  for(i = upb_msg_begin(md); !upb_msg_done(i); i = upb_msg_next(md, i)) {
    upb_fielddef *f = upb_msg_iter_field(i);
    if (!upb_isseq(f) && !upb_issubmsg(f) && !upb_isstring(f)) continue;
    void *subp = upb_value_getptr(upb_stdmsg_getptr(m, f->fval));
    if (subp == NULL) continue;
    if (upb_isseq(f)) {
      upb_stdseq_free(subp, f);
    } else if (upb_issubmsg(f)) {
      upb_stdmsg_free(subp, upb_downcast_msgdef(f->def));
    } else {
      upb_stdarray *str = subp;
      free(str->ptr);
      free(str);
    }
  }
  free(m);
}
Beispiel #25
0
VALUE layout_eq(MessageLayout* layout, void* msg1, void* msg2) {
  upb_msg_field_iter it;
  for (upb_msg_field_begin(&it, layout->msgdef);
       !upb_msg_field_done(&it);
       upb_msg_field_next(&it)) {
    const upb_fielddef* field = upb_msg_iter_field(&it);

    void* msg1_memory = slot_memory(layout, msg1, field);
    uint32_t* msg1_oneof_case = slot_oneof_case(layout, msg1, field);
    void* msg2_memory = slot_memory(layout, msg2, field);
    uint32_t* msg2_oneof_case = slot_oneof_case(layout, msg2, field);

    if (upb_fielddef_containingoneof(field)) {
      if (*msg1_oneof_case != *msg2_oneof_case ||
          (*msg1_oneof_case == upb_fielddef_number(field) &&
           !native_slot_eq(upb_fielddef_type(field),
                           msg1_memory,
                           msg2_memory))) {
        return Qfalse;
      }
    } else if (is_map_field(field)) {
      if (!Map_eq(DEREF(msg1_memory, VALUE),
                  DEREF(msg2_memory, VALUE))) {
        return Qfalse;
      }
    } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
      if (!RepeatedField_eq(DEREF(msg1_memory, VALUE),
                            DEREF(msg2_memory, VALUE))) {
        return Qfalse;
      }
    } else {
      if (slot_is_hasbit_set(layout, msg1, field) !=
	  slot_is_hasbit_set(layout, msg2, field) ||
          !native_slot_eq(upb_fielddef_type(field),
			  msg1_memory, msg2_memory)) {
        return Qfalse;
      }
    }
  }
  return Qtrue;
}
Beispiel #26
0
static void add_handlers_for_message(const void *closure, upb_handlers *h) {
    const upb_msgdef* msgdef = upb_handlers_msgdef(h);
    Descriptor* desc = ruby_to_Descriptor(get_def_obj((void*)msgdef));
    upb_msg_field_iter i;

    // If this is a mapentry message type, set up a special set of handlers and
    // bail out of the normal (user-defined) message type handling.
    if (upb_msgdef_mapentry(msgdef)) {
        add_handlers_for_mapentry(msgdef, h, desc);
        return;
    }

    // Ensure layout exists. We may be invoked to create handlers for a given
    // message if we are included as a submsg of another message type before our
    // class is actually built, so to work around this, we just create the layout
    // (and handlers, in the class-building function) on-demand.
    if (desc->layout == NULL) {
        desc->layout = create_layout(desc->msgdef);
    }

    for (upb_msg_field_begin(&i, desc->msgdef);
            !upb_msg_field_done(&i);
            upb_msg_field_next(&i)) {
        const upb_fielddef *f = upb_msg_iter_field(&i);
        size_t offset = desc->layout->fields[upb_fielddef_index(f)].offset +
                        sizeof(MessageHeader);

        if (upb_fielddef_containingoneof(f)) {
            size_t oneof_case_offset =
                desc->layout->fields[upb_fielddef_index(f)].case_offset +
                sizeof(MessageHeader);
            add_handlers_for_oneof_field(h, f, offset, oneof_case_offset);
        } else if (is_map_field(f)) {
            add_handlers_for_mapfield(h, f, offset, desc);
        } else if (upb_fielddef_isseq(f)) {
            add_handlers_for_repeated_field(h, f, offset);
        } else {
            add_handlers_for_singular_field(h, f, offset);
        }
    }
}
Beispiel #27
0
Datei: def.c Projekt: YauzZ/upb
static bool assign_msg_indices(upb_msgdef *m, upb_status *s) {
  // Sort fields.  upb internally relies on UPB_TYPE_MESSAGE fields having the
  // lowest indexes, but we do not publicly guarantee this.
  int n = upb_msgdef_numfields(m);
  upb_fielddef **fields = malloc(n * sizeof(*fields));
  if (!fields) return false;

  upb_msg_iter j;
  int i;
  m->submsg_field_count = 0;
  for(i = 0, upb_msg_begin(&j, m); !upb_msg_done(&j); upb_msg_next(&j), i++) {
    upb_fielddef *f = upb_msg_iter_field(&j);
    assert(f->msg.def == m);
    if (!upb_validate_field(f, s)) {
      free(fields);
      return false;
    }
    if (upb_fielddef_issubmsg(f)) {
      m->submsg_field_count++;
    }
    fields[i] = f;
  }

  qsort(fields, n, sizeof(*fields), cmp_fields);

  uint32_t selector = UPB_STATIC_SELECTOR_COUNT + m->submsg_field_count;
  for (i = 0; i < n; i++) {
    upb_fielddef *f = fields[i];
    f->index_ = i;
    f->selector_base = selector + upb_handlers_selectorbaseoffset(f);
    selector += upb_handlers_selectorcount(f);
  }
  m->selector_count = selector;

  free(fields);
  return false;
}
Beispiel #28
0
VALUE layout_inspect(MessageLayout* layout, void* storage) {
  VALUE str = rb_str_new2("");

  upb_msg_field_iter it;
  bool first = true;
  for (upb_msg_field_begin(&it, layout->msgdef);
       !upb_msg_field_done(&it);
       upb_msg_field_next(&it)) {
    const upb_fielddef* field = upb_msg_iter_field(&it);
    VALUE field_val = layout_get(layout, storage, field);

    if (!first) {
      str = rb_str_cat2(str, ", ");
    } else {
      first = false;
    }
    str = rb_str_cat2(str, upb_fielddef_name(field));
    str = rb_str_cat2(str, ": ");

    str = rb_str_append(str, rb_funcall(field_val, rb_intern("inspect"), 0));
  }

  return str;
}
Beispiel #29
0
MessageLayout* create_layout(const upb_msgdef* msgdef) {
  MessageLayout* layout = ALLOC(MessageLayout);
  int nfields = upb_msgdef_numfields(msgdef);
  upb_msg_field_iter it;
  upb_msg_oneof_iter oit;
  size_t off = 0;

  layout->fields = ALLOC_N(MessageField, nfields);

  size_t hasbit = 0;
  for (upb_msg_field_begin(&it, msgdef);
       !upb_msg_field_done(&it);
       upb_msg_field_next(&it)) {
    const upb_fielddef* field = upb_msg_iter_field(&it);
    if (upb_fielddef_haspresence(field)) {
      layout->fields[upb_fielddef_index(field)].hasbit = hasbit++;
    } else {
      layout->fields[upb_fielddef_index(field)].hasbit =
	  MESSAGE_FIELD_NO_HASBIT;
    }
  }

  if (hasbit != 0) {
    off += (hasbit + 8 - 1) / 8;
  }

  for (upb_msg_field_begin(&it, msgdef);
       !upb_msg_field_done(&it);
       upb_msg_field_next(&it)) {
    const upb_fielddef* field = upb_msg_iter_field(&it);
    size_t field_size;

    if (upb_fielddef_containingoneof(field)) {
      // Oneofs are handled separately below.
      continue;
    }

    // Allocate |field_size| bytes for this field in the layout.
    field_size = 0;
    if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
      field_size = sizeof(VALUE);
    } else {
      field_size = native_slot_size(upb_fielddef_type(field));
    }
    // Align current offset up to |size| granularity.
    off = align_up_to(off, field_size);
    layout->fields[upb_fielddef_index(field)].offset = off;
    layout->fields[upb_fielddef_index(field)].case_offset =
        MESSAGE_FIELD_NO_CASE;
    off += field_size;
  }

  // Handle oneofs now -- we iterate over oneofs specifically and allocate only
  // one slot per oneof.
  //
  // We assign all value slots first, then pack the 'case' fields at the end,
  // since in the common case (modern 64-bit platform) these are 8 bytes and 4
  // bytes respectively and we want to avoid alignment overhead.
  //
  // Note that we reserve 4 bytes (a uint32) per 'case' slot because the value
  // space for oneof cases is conceptually as wide as field tag numbers. In
  // practice, it's unlikely that a oneof would have more than e.g. 256 or 64K
  // members (8 or 16 bits respectively), so conceivably we could assign
  // consecutive case numbers and then pick a smaller oneof case slot size, but
  // the complexity to implement this indirection is probably not worthwhile.
  for (upb_msg_oneof_begin(&oit, msgdef);
       !upb_msg_oneof_done(&oit);
       upb_msg_oneof_next(&oit)) {
    const upb_oneofdef* oneof = upb_msg_iter_oneof(&oit);
    upb_oneof_iter fit;

    // Always allocate NATIVE_SLOT_MAX_SIZE bytes, but share the slot between
    // all fields.
    size_t field_size = NATIVE_SLOT_MAX_SIZE;
    // Align the offset.
    off = align_up_to(off, field_size);
    // Assign all fields in the oneof this same offset.
    for (upb_oneof_begin(&fit, oneof);
         !upb_oneof_done(&fit);
         upb_oneof_next(&fit)) {
      const upb_fielddef* field = upb_oneof_iter_field(&fit);
      layout->fields[upb_fielddef_index(field)].offset = off;
    }
    off += field_size;
  }

  // Now the case fields.
  for (upb_msg_oneof_begin(&oit, msgdef);
       !upb_msg_oneof_done(&oit);
       upb_msg_oneof_next(&oit)) {
    const upb_oneofdef* oneof = upb_msg_iter_oneof(&oit);
    upb_oneof_iter fit;

    size_t field_size = sizeof(uint32_t);
    // Align the offset.
    off = (off + field_size - 1) & ~(field_size - 1);
    // Assign all fields in the oneof this same offset.
    for (upb_oneof_begin(&fit, oneof);
         !upb_oneof_done(&fit);
         upb_oneof_next(&fit)) {
      const upb_fielddef* field = upb_oneof_iter_field(&fit);
      layout->fields[upb_fielddef_index(field)].case_offset = off;
    }
    off += field_size;
  }

  layout->size = off;

  layout->msgdef = msgdef;
  upb_msgdef_ref(layout->msgdef, &layout->msgdef);

  return layout;
}
Beispiel #30
0
static void putmsg(VALUE msg_rb, const Descriptor* desc,
                   upb_sink *sink, int depth) {
    MessageHeader* msg;
    upb_msg_field_iter i;
    upb_status status;

    upb_sink_startmsg(sink);

    // Protect against cycles (possible because users may freely reassign message
    // and repeated fields) by imposing a maximum recursion depth.
    if (depth > ENCODE_MAX_NESTING) {
        rb_raise(rb_eRuntimeError,
                 "Maximum recursion depth exceeded during encoding.");
    }

    TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);

    for (upb_msg_field_begin(&i, desc->msgdef);
            !upb_msg_field_done(&i);
            upb_msg_field_next(&i)) {
        upb_fielddef *f = upb_msg_iter_field(&i);
        uint32_t offset =
            desc->layout->fields[upb_fielddef_index(f)].offset +
            sizeof(MessageHeader);

        if (upb_fielddef_containingoneof(f)) {
            uint32_t oneof_case_offset =
                desc->layout->fields[upb_fielddef_index(f)].case_offset +
                sizeof(MessageHeader);
            // For a oneof, check that this field is actually present -- skip all the
            // below if not.
            if (DEREF(msg, oneof_case_offset, uint32_t) !=
                    upb_fielddef_number(f)) {
                continue;
            }
            // Otherwise, fall through to the appropriate singular-field handler
            // below.
        }

        if (is_map_field(f)) {
            VALUE map = DEREF(msg, offset, VALUE);
            if (map != Qnil) {
                putmap(map, f, sink, depth);
            }
        } else if (upb_fielddef_isseq(f)) {
            VALUE ary = DEREF(msg, offset, VALUE);
            if (ary != Qnil) {
                putary(ary, f, sink, depth);
            }
        } else if (upb_fielddef_isstring(f)) {
            VALUE str = DEREF(msg, offset, VALUE);
            if (RSTRING_LEN(str) > 0) {
                putstr(str, f, sink);
            }
        } else if (upb_fielddef_issubmsg(f)) {
            putsubmsg(DEREF(msg, offset, VALUE), f, sink, depth);
        } else {
            upb_selector_t sel = getsel(f, upb_handlers_getprimitivehandlertype(f));

#define T(upbtypeconst, upbtype, ctype, default_value)                \
  case upbtypeconst: {                                                \
      ctype value = DEREF(msg, offset, ctype);                        \
      if (value != default_value) {                                   \
        upb_sink_put##upbtype(sink, sel, value);                      \
      }                                                               \
    }                                                                 \
    break;

            switch (upb_fielddef_type(f)) {
                T(UPB_TYPE_FLOAT,  float,  float, 0.0)
                T(UPB_TYPE_DOUBLE, double, double, 0.0)
                T(UPB_TYPE_BOOL,   bool,   uint8_t, 0)
            case UPB_TYPE_ENUM:
                T(UPB_TYPE_INT32,  int32,  int32_t, 0)
                T(UPB_TYPE_UINT32, uint32, uint32_t, 0)
                T(UPB_TYPE_INT64,  int64,  int64_t, 0)
                T(UPB_TYPE_UINT64, uint64, uint64_t, 0)

            case UPB_TYPE_STRING:
            case UPB_TYPE_BYTES:
            case UPB_TYPE_MESSAGE:
                rb_raise(rb_eRuntimeError, "Internal error.");
            }

#undef T

        }
    }

    upb_sink_endmsg(sink, &status);
}