Project

General

Profile

Feature #14473 ยป v6-0001-range.c-allow-cover-to-accept-Range-argument.patch

owst (Owen Stephens), 08/01/2018 11:39 PM

View differences:

range.c
1326 1326
    return Qundef;
1327 1327
}
1328 1328

  
1329
static int r_cover_range_p(VALUE range, VALUE beg, VALUE end, VALUE val);
1329 1330

  
1330 1331
/*
1331 1332
 *  call-seq:
1332
 *     rng.cover?(obj)  ->  true or false
1333
 *     rng.cover?(obj)   ->  true or false
1334
 *     rng.cover?(range) ->  true or false
1333 1335
 *
1334 1336
 *  Returns <code>true</code> if +obj+ is between the begin and end of
1335 1337
 *  the range.
......
1337 1339
 *  This tests <code>begin <= obj <= end</code> when #exclude_end? is +false+
1338 1340
 *  and <code>begin <= obj < end</code> when #exclude_end? is +true+.
1339 1341
 *
1340
 *     ("a".."z").cover?("c")    #=> true
1341
 *     ("a".."z").cover?("5")    #=> false
1342
 *     ("a".."z").cover?("cc")   #=> true
1342
 *  Returns <code>true</code> for a Range when it is covered by the receiver,
1343
 *  by comparing the begin and end values directly. In the specific case of
1344
 *  <code>(a..b).cover?(c...d)</code> with <code>a <= c && b < d</code> this is
1345
 *  not possible, and <code>(c...d).max</code> must be calculated, which may
1346
 *  exhibit poor performance if c is non-numeric. Returns <code>false</code> if
1347
 *  the begin value of the Range is larger than the end value.
1348
 *
1349
 *     ("a".."z").cover?("c")  #=> true
1350
 *     ("a".."z").cover?("5")  #=> false
1351
 *     ("a".."z").cover?("cc") #=> true
1352
 *     (1..5).cover?(2..3)     #=> true
1353
 *     (1..5).cover?(0..6)     #=> false
1354
 *     (1..5).cover?(1...6)    #=> true
1343 1355
 */
1344 1356

  
1345 1357
static VALUE
......
1349 1361

  
1350 1362
    beg = RANGE_BEG(range);
1351 1363
    end = RANGE_END(range);
1364

  
1365
    if (rb_obj_is_kind_of(val, rb_cRange)) {
1366
    return RBOOL(r_cover_range_p(range, beg, end, val));
1367
    }
1352 1368
    return r_cover_p(range, beg, end, val);
1353 1369
}
1354 1370

  
1371
static VALUE
1372
r_call_max(VALUE r)
1373
{
1374
    return rb_funcallv(r, rb_intern("max"), 0, 0);
1375
}
1376

  
1377
static int
1378
r_cover_range_p(VALUE range, VALUE beg, VALUE end, VALUE val)
1379
{
1380
    VALUE val_beg, val_end, val_max;
1381
    int cmp_end;
1382

  
1383
    val_beg = RANGE_BEG(val);
1384
    val_end = RANGE_END(val);
1385

  
1386
    if (!NIL_P(end) && NIL_P(val_end)) return FALSE;
1387
    if (!NIL_P(val_end) && r_less(val_beg, val_end) > -EXCL(val)) return FALSE;
1388
    if (!r_cover_p(range, beg, end, val_beg)) return FALSE;
1389

  
1390
    cmp_end = r_less(end, val_end);
1391

  
1392
    if (EXCL(range) == EXCL(val)) {
1393
    return cmp_end >= 0;
1394
    } else if (EXCL(range)) {
1395
    return cmp_end > 0;
1396
    } else if (cmp_end >= 0) {
1397
    return TRUE;
1398
    }
1399

  
1400
    val_max = rb_rescue2(r_call_max, val, NULL, Qnil, rb_eTypeError, (VALUE)0);
1401
    if (val_max == Qnil) return FALSE;
1402

  
1403
    return r_less(end, val_max) >= 0;
1404
}
1405

  
1355 1406
static VALUE
1356 1407
r_cover_p(VALUE range, VALUE beg, VALUE end, VALUE val)
1357 1408
{
test/ruby/test_range.rb
521 521
    assert_not_operator(5..., :cover?, 0)
522 522
    assert_not_operator(5..., :cover?, "a")
523 523
    assert_operator(5.., :cover?, 10)
524

  
525
    assert_operator(2..5, :cover?, 2..5)
526
    assert_operator(2...6, :cover?, 2...6)
527
    assert_operator(2...6, :cover?, 2..5)
528
    assert_operator(2..5, :cover?, 2...6)
529
    assert_operator(2..5, :cover?, 2..4)
530
    assert_operator(2..5, :cover?, 2...4)
531
    assert_operator(2..5, :cover?, 2...5)
532
    assert_operator(2..5, :cover?, 3..5)
533
    assert_operator(2..5, :cover?, 3..4)
534
    assert_operator(2..5, :cover?, 3...6)
535
    assert_operator(2...6, :cover?, 2...5)
536
    assert_operator(2...6, :cover?, 2..5)
537
    assert_operator(2..6, :cover?, 2...6)
538
    assert_operator(2.., :cover?, 2..)
539
    assert_operator(2.., :cover?, 3..)
540
    assert_operator(1.., :cover?, 1..10)
541
    assert_operator(2.0..5.0, :cover?, 2..3)
542
    assert_operator(2..5, :cover?, 2.0..3.0)
543
    assert_operator(2..5, :cover?, 2.0...3.0)
544
    assert_operator(2..5, :cover?, 2.0...5.0)
545
    assert_operator(2.0..5.0, :cover?, 2.0...3.0)
546
    assert_operator(2.0..5.0, :cover?, 2.0...5.0)
547
    assert_operator('aa'..'zz', :cover?, 'aa'...'bb')
548

  
549
    assert_not_operator(2..5, :cover?, 1..5)
550
    assert_not_operator(2...6, :cover?, 1..5)
551
    assert_not_operator(2..5, :cover?, 1...6)
552
    assert_not_operator(1..3, :cover?, 1...6)
553
    assert_not_operator(2..5, :cover?, 2..6)
554
    assert_not_operator(2...6, :cover?, 2..6)
555
    assert_not_operator(2...6, :cover?, 2...7)
556
    assert_not_operator(2..3, :cover?, 1..4)
557
    assert_not_operator(1..2, :cover?, 1.0..3.0)
558
    assert_not_operator(1.0..2.9, :cover?, 1.0..3.0)
559
    assert_not_operator(1..2, :cover?, 4..3)
560
    assert_not_operator(2..1, :cover?, 1..2)
561
    assert_not_operator(1...2, :cover?, 1...3)
562
    assert_not_operator(2.., :cover?, 1..)
563
    assert_not_operator(2.., :cover?, 1..10)
564
    assert_not_operator(1..10, :cover?, 1..)
565
    assert_not_operator(1..5, :cover?, 3..2)
566
    assert_not_operator(1..10, :cover?, 3...2)
567
    assert_not_operator(1..10, :cover?, 3...3)
568
    assert_not_operator('aa'..'zz', :cover?, 'aa'...'zzz')
569
    assert_not_operator(1..10, :cover?, 1...10.1)
524 570
  end
525 571

  
526 572
  def test_beg_len
527
-