示例#1
0
文件: map.c 项目: Livefyre/protobuf
// Used by Google::Protobuf.deep_copy but not exposed directly.
VALUE Map_deep_copy(VALUE _self) {
  Map* self = ruby_to_Map(_self);
  VALUE new_map = Map_new_this_type(_self);
  Map* new_self = ruby_to_Map(new_map);

  upb_strtable_iter it;
  for (upb_strtable_begin(&it, &self->table);
       !upb_strtable_done(&it);
       upb_strtable_next(&it)) {

    upb_value v = upb_strtable_iter_value(&it);
    void* mem = value_memory(&v);
    upb_value dup;
    void* dup_mem = value_memory(&dup);
    native_slot_deep_copy(self->value_type, dup_mem, mem);

    if (!upb_strtable_insert2(&new_self->table,
                              upb_strtable_iter_key(&it),
                              upb_strtable_iter_keylength(&it),
                              dup)) {
      rb_raise(rb_eRuntimeError, "Error inserting value into new table");
    }
  }

  return new_map;
}
示例#2
0
文件: map.c 项目: radavies/protobuf
/*
 * call-seq:
 *     Map.[]=(key, value) => value
 *
 * Inserts or overwrites the value at the given key with the given new value.
 * Throws an exception if the key type is incorrect. Returns the new value that
 * was just inserted.
 */
VALUE Map_index_set(VALUE _self, VALUE key, VALUE value) {
    Map* self = ruby_to_Map(_self);

    char keybuf[TABLE_KEY_BUF_LENGTH];
    const char* keyval = NULL;
    size_t length = 0;
    table_key(self, key, keybuf, &keyval, &length);

    upb_value v;
    void* mem = value_memory(&v);
    native_slot_set(self->value_type, self->value_type_class, mem, value);

    // Replace any existing value by issuing a 'remove' operation first.
    upb_strtable_remove2(&self->table, keyval, length, NULL);
    if (!upb_strtable_insert2(&self->table, keyval, length, v)) {
        rb_raise(rb_eRuntimeError, "Could not insert into table");
    }

    // Ruby hashmap's :[]= method also returns the inserted value.
    return value;
}
示例#3
0
文件: map.c 项目: Livefyre/protobuf
// Used only internally -- shared by #merge and #initialize.
VALUE Map_merge_into_self(VALUE _self, VALUE hashmap) {
  if (TYPE(hashmap) == T_HASH) {
    rb_hash_foreach(hashmap, merge_into_self_callback, _self);
  } else if (RB_TYPE_P(hashmap, T_DATA) && RTYPEDDATA_P(hashmap) &&
             RTYPEDDATA_TYPE(hashmap) == &Map_type) {

    Map* self = ruby_to_Map(_self);
    Map* other = ruby_to_Map(hashmap);
    upb_strtable_iter it;

    if (self->key_type != other->key_type ||
        self->value_type != other->value_type ||
        self->value_type_class != other->value_type_class) {
      rb_raise(rb_eArgError, "Attempt to merge Map with mismatching types");
    }

    for (upb_strtable_begin(&it, &other->table);
         !upb_strtable_done(&it);
         upb_strtable_next(&it)) {

      // Replace any existing value by issuing a 'remove' operation first.
      upb_value v;
      upb_value oldv;
      upb_strtable_remove2(&self->table,
                           upb_strtable_iter_key(&it),
                           upb_strtable_iter_keylength(&it),
                           &oldv);

      v = upb_strtable_iter_value(&it);
      upb_strtable_insert2(&self->table,
                           upb_strtable_iter_key(&it),
                           upb_strtable_iter_keylength(&it),
                           v);
    }
  } else {
    rb_raise(rb_eArgError, "Unknown type merging into Map");
  }
  return _self;
}