Project

General

Profile

Feature #12719 ยป struct_merge.patch

halogenandtoast (Matthew Mongeau), 09/05/2016 02:55 AM

View differences:

ChangeLog
1
Fri Sep  2 17:27:31 2016  Matthew Mongeau <halogenandtoast@gmail.com>
2

  
3
	* struct.c (rb_struct_update): Add Struct#merge and Struct#merge!
4
	for updating structs
5

  
1 6
Fri Sep  2 16:06:59 2016  Nobuyoshi Nakada  <nobu@ruby-lang.org>
2 7

  
3 8
	* internal.h (MEMO_V1_SET, MEMO_V2_SET): fix typos.  use the macro
struct.c
894 894
    return RSTRUCT_GET(s, i);
895 895
}
896 896

  
897
static int
898
value_update(VALUE key, VALUE value, VALUE s)
899
{
900
    rb_struct_aset(s, key, value);
901
    return ST_CONTINUE;
902
}
903

  
904
/*
905
 *  call-seq:
906
 *     struct.merge!(hash)    -> struct
907
 *
908
 *  Updates the values of the struct using the keys and values of the hash
909
 *
910
 *     Point = Struct.new(:x, :y)
911
 *     hash = { "x" => 5 }
912
 *     point = Point.new(1, 2)
913
 *     point.merge!(hash)
914
 *
915
 *     point.x    #=> 5
916
 */
917

  
918
VALUE
919
rb_struct_update(VALUE self, VALUE hash)
920
{
921
    VALUE converted_hash = rb_convert_type(hash, T_HASH, "Hash", "to_hash");
922

  
923
    rb_hash_foreach(converted_hash, value_update, self);
924

  
925
    return self;
926
}
927

  
928
/*
929
 *  call-seq:
930
 *     struct.merge(hash)    -> new_struct
931
 *
932
 *  Returns a new struct with updated values using the keys and values of
933
 *  the hash
934
 *
935
 *     Point = Struct.new(:x, :y)
936
 *     p = Point.new(1, 2)
937
 *     p2 = p.merge(y: 20)
938
 *
939
 *     p.y   #=> 2
940
 *     p2.y    #=> 20
941
 */
942

  
943
VALUE
944
rb_struct_merge(VALUE self, VALUE hash)
945
{
946
    VALUE dup = rb_obj_dup(self);
947
    return rb_struct_update(dup, hash);
948
}
949

  
897 950
/*
898 951
 *  call-seq:
899 952
 *     struct[member] = obj    -> obj
......
1215 1268

  
1216 1269
    rb_define_method(rb_cStruct, "members", rb_struct_members_m, 0);
1217 1270
    rb_define_method(rb_cStruct, "dig", rb_struct_dig, -1);
1271

  
1272
    rb_define_method(rb_cStruct, "merge", rb_struct_merge, 1);
1273
    rb_define_method(rb_cStruct, "merge!", rb_struct_update, 1);
1218 1274
}
1219 1275

  
1220 1276
#undef rb_intern
test/ruby/test_struct.rb
367 367
    assert_nil(o.dig(:b, 0))
368 368
  end
369 369

  
370
  def test_merge!
371
    klass = @Struct.new(:a, :b)
372
    o = klass.new(1, 2)
373
    o.merge!(a: 10)
374
    assert_equal(o.a, 10)
375
    assert_equal(o.b, 2)
376

  
377
    o.merge!("b" => 5)
378
    assert_equal(o.b, 5)
379

  
380
    assert_raise(TypeError) {
381
      o.merge(0)
382
    }
383
  end
384

  
385
  def test_merge
386
    klass = @Struct.new(:a, :b)
387
    o = klass.new(1, 2)
388
    p = o.merge(a: 10)
389
    assert_equal(p.a, 10)
390
    assert_equal(p.b, 2)
391
    assert_equal(o.a, 1)
392
    assert_equal(o.b, 2)
393

  
394
    assert_raise(TypeError) {
395
      o.merge(0)
396
    }
397
  end
398

  
370 399
  def test_new_dupilicate
371 400
    bug12291 = '[ruby-core:74971] [Bug #12291]'
372 401
    assert_raise_with_message(ArgumentError, /duplicate member/, bug12291) {