Ejemplo n.º 1
0
/*
 * call-seq:
 *     RepeatedField.+(other) => repeated field
 *
 * Returns a new repeated field that contains the concatenated list of this
 * repeated field's elements and other's elements. The other (second) list may
 * be either another repeated field or a Ruby array.
 */
VALUE RepeatedField_plus(VALUE _self, VALUE list) {
  VALUE dupped = RepeatedField_dup(_self);

  if (TYPE(list) == T_ARRAY) {
    for (int i = 0; i < RARRAY_LEN(list); i++) {
      VALUE elem = rb_ary_entry(list, i);
      RepeatedField_push(dupped, elem);
    }
  } else if (RB_TYPE_P(list, T_DATA) && RTYPEDDATA_P(list) &&
             RTYPEDDATA_TYPE(list) == &RepeatedField_type) {
    RepeatedField* self = ruby_to_RepeatedField(_self);
    RepeatedField* list_rptfield = ruby_to_RepeatedField(list);
    if (self->field_type != list_rptfield->field_type ||
        self->field_type_class != list_rptfield->field_type_class) {
      rb_raise(rb_eArgError,
               "Attempt to append RepeatedField with different element type.");
    }
    for (int i = 0; i < list_rptfield->size; i++) {
      void* mem = RepeatedField_index_native(list, i);
      RepeatedField_push_native(dupped, mem);
    }
  } else {
    rb_raise(rb_eArgError, "Unknown type appending to RepeatedField");
  }

  return dupped;
}
Ejemplo n.º 2
0
/*
 * call-seq:
 *     RepeatedField.==(other) => boolean
 *
 * Compares this repeated field to another. Repeated fields are equal if their
 * element types are equal, their lengths are equal, and each element is equal.
 * Elements are compared as per normal Ruby semantics, by calling their :==
 * methods (or performing a more efficient comparison for primitive types).
 *
 * Repeated fields with dissimilar element types are never equal, even if value
 * comparison (for example, between integers and floats) would have otherwise
 * indicated that every element has equal value.
 */
VALUE RepeatedField_eq(VALUE _self, VALUE _other) {
  if (_self == _other) {
    return Qtrue;
  }
  RepeatedField* self = ruby_to_RepeatedField(_self);

  if (TYPE(_other) == T_ARRAY) {
    VALUE self_ary = RepeatedField_to_ary(_self);
    return rb_equal(self_ary, _other);
  }

  RepeatedField* other = ruby_to_RepeatedField(_other);
  if (self->field_type != other->field_type ||
      self->field_type_class != other->field_type_class ||
      self->size != other->size) {
    return Qfalse;
  }

  upb_fieldtype_t field_type = self->field_type;
  size_t elem_size = native_slot_size(field_type);
  size_t off = 0;
  for (int i = 0; i < self->size; i++, off += elem_size) {
    void* self_mem = ((uint8_t *)self->elements) + off;
    void* other_mem = ((uint8_t *)other->elements) + off;
    if (!native_slot_eq(field_type, self_mem, other_mem)) {
      return Qfalse;
    }
  }
  return Qtrue;
}
Ejemplo n.º 3
0
/*
 * call-seq:
 *     RepeatedField.[]=(index, value)
 *
 * Sets the element at the given index. On out-of-bounds assignments, extends
 * the array and fills the hole (if any) with default values.
 */
VALUE RepeatedField_index_set(VALUE _self, VALUE _index, VALUE val) {
  RepeatedField* self = ruby_to_RepeatedField(_self);
  upb_fieldtype_t field_type = self->field_type;
  VALUE field_type_class = self->field_type_class;
  int element_size = native_slot_size(field_type);

  int index = index_position(_index, self);
  if (index < 0 || index >= (INT_MAX - 1)) {
    return Qnil;
  }
  if (index >= self->size) {
    RepeatedField_reserve(self, index + 1);
    upb_fieldtype_t field_type = self->field_type;
    int element_size = native_slot_size(field_type);
    for (int i = self->size; i <= index; i++) {
      void* elem = (void *)(((uint8_t *)self->elements) + i * element_size);
      native_slot_init(field_type, elem);
    }
    self->size = index + 1;
  }

  void* memory = (void *) (((uint8_t *)self->elements) + index * element_size);
  native_slot_set(field_type, field_type_class, memory, val);
  return Qnil;
}
Ejemplo n.º 4
0
static void check_repeated_field_type(VALUE val, const upb_fielddef* field) {
  RepeatedField* self;
  assert(upb_fielddef_label(field) == UPB_LABEL_REPEATED);

  if (!RB_TYPE_P(val, T_DATA) || !RTYPEDDATA_P(val) ||
      RTYPEDDATA_TYPE(val) != &RepeatedField_type) {
    rb_raise(cTypeError, "Expected repeated field array");
  }

  self = ruby_to_RepeatedField(val);
  if (self->field_type != upb_fielddef_type(field)) {
    rb_raise(cTypeError, "Repeated field array has wrong element type");
  }

  if (self->field_type == UPB_TYPE_MESSAGE) {
    if (self->field_type_class !=
        Descriptor_msgclass(get_def_obj(upb_fielddef_subdef(field)))) {
      rb_raise(cTypeError,
               "Repeated field array has wrong message class");
    }
  }


  if (self->field_type == UPB_TYPE_ENUM) {
    if (self->field_type_class !=
        EnumDescriptor_enummodule(get_def_obj(upb_fielddef_subdef(field)))) {
      rb_raise(cTypeError,
               "Repeated field array has wrong enum class");
    }
  }
}
Ejemplo n.º 5
0
// Internal only: used by Google::Protobuf.deep_copy.
VALUE RepeatedField_deep_copy(VALUE _self) {
  RepeatedField* self = ruby_to_RepeatedField(_self);
  VALUE new_rptfield = RepeatedField_new_this_type(_self);
  RepeatedField* new_rptfield_self = ruby_to_RepeatedField(new_rptfield);
  RepeatedField_reserve(new_rptfield_self, self->size);
  upb_fieldtype_t field_type = self->field_type;
  size_t elem_size = native_slot_size(field_type);
  size_t off = 0;
  for (int i = 0; i < self->size; i++, off += elem_size) {
    void* to_mem = (uint8_t *)new_rptfield_self->elements + off;
    void* from_mem = (uint8_t *)self->elements + off;
    native_slot_deep_copy(field_type, to_mem, from_mem);
    new_rptfield_self->size++;
  }

  return new_rptfield;
}
Ejemplo n.º 6
0
/*
 * call-seq:
 *     RepeatedField.concat(other) => self
 *
 * concats the passed in array to self.  Returns a Ruby array.
 */
VALUE RepeatedField_concat(VALUE _self, VALUE list) {
  RepeatedField* self = ruby_to_RepeatedField(_self);
  Check_Type(list, T_ARRAY);
  for (int i = 0; i < RARRAY_LEN(list); i++) {
    RepeatedField_push(_self, rb_ary_entry(list, i));
  }
  return _self;
}
Ejemplo n.º 7
0
/*
 * call-seq:
 *     RepeatedField.replace(list)
 *
 * Replaces the contents of the repeated field with the given list of elements.
 */
VALUE RepeatedField_replace(VALUE _self, VALUE list) {
  RepeatedField* self = ruby_to_RepeatedField(_self);
  Check_Type(list, T_ARRAY);
  self->size = 0;
  for (int i = 0; i < RARRAY_LEN(list); i++) {
    RepeatedField_push(_self, rb_ary_entry(list, i));
  }
  return list;
}
Ejemplo n.º 8
0
// Used by parsing handlers.
void RepeatedField_push_native(VALUE _self, void* data) {
  RepeatedField* self = ruby_to_RepeatedField(_self);
  upb_fieldtype_t field_type = self->field_type;
  int element_size = native_slot_size(field_type);
  RepeatedField_reserve(self, self->size + 1);
  int index = self->size;
  void* memory = (void *) (((uint8_t *)self->elements) + index * element_size);
  memcpy(memory, data, element_size);
  self->size++;
}
Ejemplo n.º 9
0
/*
 * call-seq:
 *     RepeatedField.push(value)
 *
 * Adds a new element to the repeated field.
 */
VALUE RepeatedField_push(VALUE _self, VALUE val) {
  RepeatedField* self = ruby_to_RepeatedField(_self);
  upb_fieldtype_t field_type = self->field_type;
  int element_size = native_slot_size(field_type);
  RepeatedField_reserve(self, self->size + 1);
  int index = self->size;
  void* memory = (void *) (((uint8_t *)self->elements) + index * element_size);
  native_slot_set(field_type, self->field_type_class, memory, val);
  // native_slot_set may raise an error; bump index only after set.
  self->size++;
  return _self;
}
Ejemplo n.º 10
0
static VALUE RepeatedField_new_this_type(VALUE _self) {
  RepeatedField* self = ruby_to_RepeatedField(_self);
  VALUE new_rptfield = Qnil;
  VALUE element_type = fieldtype_to_ruby(self->field_type);
  if (self->field_type_class != Qnil) {
    new_rptfield = rb_funcall(CLASS_OF(_self), rb_intern("new"), 2,
                              element_type, self->field_type_class);
  } else {
    new_rptfield = rb_funcall(CLASS_OF(_self), rb_intern("new"), 1,
                              element_type);
  }
  return new_rptfield;
}
Ejemplo n.º 11
0
/*
 * call-seq:
 *     RepeatedField.pop => value
 *
 * Removes the last element and returns it. Throws an exception if the repeated
 * field is empty.
 */
VALUE RepeatedField_pop(VALUE _self) {
  RepeatedField* self = ruby_to_RepeatedField(_self);
  upb_fieldtype_t field_type = self->field_type;
  VALUE field_type_class = self->field_type_class;
  int element_size = native_slot_size(field_type);
  if (self->size == 0) {
    rb_raise(rb_eRangeError, "Pop from empty repeated field is not allowed.");
  }
  int index = self->size - 1;
  void* memory = (void *) (((uint8_t *)self->elements) + index * element_size);
  VALUE ret = native_slot_get(field_type, field_type_class, memory);
  self->size--;
  return ret;
}
Ejemplo n.º 12
0
/*
 * Private ruby method, used by RepeatedField.pop
 */
VALUE RepeatedField_pop_one(VALUE _self) {
  RepeatedField* self = ruby_to_RepeatedField(_self);
  upb_fieldtype_t field_type = self->field_type;
  VALUE field_type_class = self->field_type_class;
  int element_size = native_slot_size(field_type);
  if (self->size == 0) {
    return Qnil;
  }
  int index = self->size - 1;
  void* memory = (void *) (((uint8_t *)self->elements) + index * element_size);
  VALUE ret = native_slot_get(field_type, field_type_class, memory);
  self->size--;
  return ret;
}
Ejemplo n.º 13
0
/*
 * call-seq:
 *     RepeatedField.[](index) => value
 *
 * Accesses the element at the given index. Returns nil on out-of-bounds
 */
VALUE RepeatedField_index(VALUE _self, VALUE _index) {
  RepeatedField* self = ruby_to_RepeatedField(_self);
  int element_size = native_slot_size(self->field_type);
  upb_fieldtype_t field_type = self->field_type;
  VALUE field_type_class = self->field_type_class;

  int index = index_position(_index, self);
  if (index < 0 || index >= self->size) {
    return Qnil;
  }

  void* memory = (void *) (((uint8_t *)self->elements) + index * element_size);
  return native_slot_get(field_type, field_type_class, memory);
}
Ejemplo n.º 14
0
/*
 * call-seq:
 *     RepeatedField.to_ary => array
 *
 * Used when converted implicitly into array, e.g. compared to an Array.
 * Also called as a fallback of Object#to_a
 */
VALUE RepeatedField_to_ary(VALUE _self) {
  RepeatedField* self = ruby_to_RepeatedField(_self);
  upb_fieldtype_t field_type = self->field_type;

  size_t elem_size = native_slot_size(field_type);
  size_t off = 0;
  VALUE ary = rb_ary_new2(self->size);
  for (int i = 0; i < self->size; i++, off += elem_size) {
    void* mem = ((uint8_t *)self->elements) + off;
    VALUE elem = native_slot_get(field_type, self->field_type_class, mem);
    rb_ary_push(ary, elem);
  }
  return ary;
}
Ejemplo n.º 15
0
/*
 * call-seq:
 *     RepeatedField.[](index) => value
 *
 * Accesses the element at the given index. Throws an exception on out-of-bounds
 * errors.
 */
VALUE RepeatedField_index(VALUE _self, VALUE _index) {
  RepeatedField* self = ruby_to_RepeatedField(_self);
  int element_size = native_slot_size(self->field_type);
  upb_fieldtype_t field_type = self->field_type;
  VALUE field_type_class = self->field_type_class;

  int index = NUM2INT(_index);
  if (index < 0 || index >= self->size) {
    rb_raise(rb_eRangeError, "Index out of range");
  }

  void* memory = (void *) (((uint8_t *)self->elements) + index * element_size);
  return native_slot_get(field_type, field_type_class, memory);
}
Ejemplo n.º 16
0
/*
 * call-seq:
 *     RepeatedField.each(&block)
 *
 * Invokes the block once for each element of the repeated field. RepeatedField
 * also includes Enumerable; combined with this method, the repeated field thus
 * acts like an ordinary Ruby sequence.
 */
VALUE RepeatedField_each(VALUE _self) {
  RepeatedField* self = ruby_to_RepeatedField(_self);
  upb_fieldtype_t field_type = self->field_type;
  VALUE field_type_class = self->field_type_class;
  int element_size = native_slot_size(field_type);

  size_t off = 0;
  for (int i = 0; i < self->size; i++, off += element_size) {
    void* memory = (void *) (((uint8_t *)self->elements) + off);
    VALUE val = native_slot_get(field_type, field_type_class, memory);
    rb_yield(val);
  }
  return _self;
}
Ejemplo n.º 17
0
VALUE RepeatedField_subarray(VALUE _self, long beg, long len) {
  RepeatedField* self = ruby_to_RepeatedField(_self);
  int element_size = native_slot_size(self->field_type);
  upb_fieldtype_t field_type = self->field_type;
  VALUE field_type_class = self->field_type_class;

  size_t off = beg * element_size;
  VALUE ary = rb_ary_new2(len);
  for (int i = beg; i < beg + len; i++, off += element_size) {
    void* mem = ((uint8_t *)self->elements) + off;
    VALUE elem = native_slot_get(field_type, field_type_class, mem);
    rb_ary_push(ary, elem);
  }
  return ary;
}
Ejemplo n.º 18
0
/*
 * call-seq:
 *     RepeatedField.[](index) => value
 *
 * Accesses the element at the given index. Returns nil on out-of-bounds
 */
VALUE RepeatedField_index(int argc, VALUE* argv, VALUE _self) {
  RepeatedField* self = ruby_to_RepeatedField(_self);
  int element_size = native_slot_size(self->field_type);
  upb_fieldtype_t field_type = self->field_type;
  VALUE field_type_class = self->field_type_class;

  VALUE arg = argv[0];
  long beg, len;

  if (argc == 1){
    if (FIXNUM_P(arg)) {
      /* standard case */
      int index = index_position(argv[0], self);
      if (index < 0 || index >= self->size) {
        return Qnil;
      }
      void* memory = (void *) (((uint8_t *)self->elements) +
                               index * element_size);
      return native_slot_get(field_type, field_type_class, memory);
    }else{
      /* check if idx is Range */
      size_t off;
      switch (rb_range_beg_len(arg, &beg, &len, self->size, 0)) {
        case Qfalse:
          break;
        case Qnil:
          return Qnil;
        default:
          return RepeatedField_subarray(_self, beg, len);
      }
    }
  }
  /* assume 2 arguments */
  beg = NUM2LONG(argv[0]);
  len = NUM2LONG(argv[1]);
  if (beg < 0) {
    beg += self->size;
  }
  if (beg >= self->size) {
    return Qnil;
  }
  return RepeatedField_subarray(_self, beg, len);
}
Ejemplo n.º 19
0
/*
 * call-seq:
 *     RepeatedField.hash => hash_value
 *
 * Returns a hash value computed from this repeated field's elements.
 */
VALUE RepeatedField_hash(VALUE _self) {
  RepeatedField* self = ruby_to_RepeatedField(_self);

  VALUE hash = LL2NUM(0);

  upb_fieldtype_t field_type = self->field_type;
  VALUE field_type_class = self->field_type_class;
  size_t elem_size = native_slot_size(field_type);
  size_t off = 0;
  for (int i = 0; i < self->size; i++, off += elem_size) {
    void* mem = ((uint8_t *)self->elements) + off;
    VALUE elem = native_slot_get(field_type, field_type_class, mem);
    hash = rb_funcall(hash, rb_intern("<<"), 1, INT2NUM(2));
    hash = rb_funcall(hash, rb_intern("^"), 1,
                      rb_funcall(elem, rb_intern("hash"), 0));
  }

  return hash;
}
Ejemplo n.º 20
0
void RepeatedField_init_args(int argc, VALUE* argv,
                             VALUE _self) {
  RepeatedField* self = ruby_to_RepeatedField(_self);
  VALUE ary = Qnil;
  if (argc < 1) {
    rb_raise(rb_eArgError, "Expected at least 1 argument.");
  }
  self->field_type = ruby_to_fieldtype(argv[0]);

  if (self->field_type == UPB_TYPE_MESSAGE ||
      self->field_type == UPB_TYPE_ENUM) {
    if (argc < 2) {
      rb_raise(rb_eArgError, "Expected at least 2 arguments for message/enum.");
    }
    self->field_type_class = argv[1];
    if (argc > 2) {
      ary = argv[2];
    }
    validate_type_class(self->field_type, self->field_type_class);
  } else {
    if (argc > 2) {
      rb_raise(rb_eArgError, "Too many arguments: expected 1 or 2.");
    }
    if (argc > 1) {
      ary = argv[1];
    }
  }

  if (ary != Qnil) {
    if (!RB_TYPE_P(ary, T_ARRAY)) {
      rb_raise(rb_eArgError, "Expected array as initialize argument");
    }
    for (int i = 0; i < RARRAY_LEN(ary); i++) {
      RepeatedField_push(_self, rb_ary_entry(ary, i));
    }
  }
}
Ejemplo n.º 21
0
/*
 * call-seq:
 *     RepeatedField.length
 *
 * Returns the length of this repeated field.
 */
VALUE RepeatedField_length(VALUE _self) {
  RepeatedField* self = ruby_to_RepeatedField(_self);
  return INT2NUM(self->size);
}
Ejemplo n.º 22
0
void* RepeatedField_index_native(VALUE _self, int index) {
  RepeatedField* self = ruby_to_RepeatedField(_self);
  upb_fieldtype_t field_type = self->field_type;
  int element_size = native_slot_size(field_type);
  return ((uint8_t *)self->elements) + index * element_size;
}
Ejemplo n.º 23
0
/*
 * call-seq:
 *     RepeatedField.clear
 *
 * Clears (removes all elements from) this repeated field.
 */
VALUE RepeatedField_clear(VALUE _self) {
  RepeatedField* self = ruby_to_RepeatedField(_self);
  self->size = 0;
  return _self;
}