Project

General

Profile

Feature #14473 ยป 0001-range.c-add-subset-superset-methods.patch

owst (Owen Stephens), 02/22/2018 06:10 PM

View differences:

range.c
18 18
#include <math.h>
19 19

  
20 20
VALUE rb_cRange;
21
static ID id_beg, id_end, id_excl, id_integer_p, id_div;
21
static ID id_beg, id_end, id_excl, id_integer_p, id_div, id_min, id_max;
22 22
#define id_cmp idCmp
23 23
#define id_succ idSucc
24 24

  
......
1201 1201
    return Qfalse;
1202 1202
}
1203 1203

  
1204
/*
1205
 *  call-seq:
1206
 *     rng.subset?(obj)  ->  true or false
1207
 *     rng <= obj        ->  true or false
1208
 *
1209
 *  Returns <code>true</code> if +obj+ is a Range and it includes the first and
1210
 *  last elements of the range, <code>false</code> otherwise.
1211
 *  Raises +TypeError+ if +obj+ is not a Range.
1212
 *
1213
 *     ("b".."d").subset?("b".."e") #=> true
1214
 *     ("b".."e").subset?("b".."e") #=> true
1215
 *     ("a".."e").subset?("b".."e") #=> false
1216
 */
1217

  
1218
static VALUE
1219
range_subset(VALUE range, VALUE obj)
1220
{
1221
    if (!rb_obj_is_kind_of(obj, rb_cRange))
1222
        rb_raise(rb_eTypeError, "not a range object");
1223

  
1224
    VALUE min = rb_funcall(range, id_min, 0);
1225
    if (min == Qnil)
1226
        return Qtrue;
1227

  
1228
    if (range_cover(obj, min) &&
1229
        range_cover(obj, rb_funcall(range, id_max, 0))) {
1230
    return Qtrue;
1231
    }
1232
    return Qfalse;
1233
}
1234

  
1235
static VALUE
1236
r_differ_at(VALUE range, VALUE obj, ID id)
1237
{
1238
    return !rb_equal(rb_funcall(range, id, 0), rb_funcall(obj, id, 0));
1239
}
1240

  
1241
/*
1242
 *  call-seq:
1243
 *     rng.strict_subset?(obj)  ->  true or false
1244
 *     rng < obj                ->  true or false
1245
 *
1246
 *  Returns <code>true</code> if +obj+ is a Range and it includes the first and
1247
 *  last elements of the range, but is not equal to the range,
1248
 *  <code>false</code> otherwise.
1249
 *  Raises +TypeError+ if +obj+ is not a Range.
1250
 *
1251
 *     ("b".."d").strict_subset?("b".."e") #=> true
1252
 *     ("b".."e").strict_subset?("b".."e") #=> false
1253
 *     ("a".."e").strict_subset?("b".."e") #=> false
1254
 */
1255

  
1256
static VALUE
1257
range_strict_subset(VALUE range, VALUE obj)
1258
{
1259
    if (range_subset(range, obj) &&
1260
        (r_differ_at(range, obj, id_min) || r_differ_at(range, obj, id_max)) {
1261
    return Qtrue;
1262
    }
1263
    return Qfalse;
1264
}
1265

  
1266
/*
1267
 *  call-seq:
1268
 *     rng.superset?(obj)  ->  true or false
1269
 *     rng >= obj          ->  true or false
1270
 *
1271
 *  Returns <code>true</code> if +obj+ is a Range, and its first and last
1272
 *  elements are included in the range, <code>false</code> otherwise.
1273
 *  Raises +TypeError+ if +obj+ is not a Range.
1274
 *
1275
 *     ("b".."e").superset?("b".."d") #=> true
1276
 *     ("b".."e").superset?("b".."e") #=> true
1277
 *     ("b".."e").superset?("a".."e") #=> false
1278
 */
1279

  
1280
static VALUE
1281
range_superset(VALUE range, VALUE obj)
1282
{
1283
    if (!rb_obj_is_kind_of(obj, rb_cRange))
1284
        rb_raise(rb_eTypeError, "not a range object");
1285

  
1286
    return range_subset(obj, range);
1287
}
1288

  
1289
/*
1290
 *  call-seq:
1291
 *     rng.strict_superset?(obj)  ->  true or false
1292
 *     rng > obj                  ->  true or false
1293
 *
1294
 *  Returns <code>true</code> if +obj+ is a Range, and its first and last
1295
 *  elements are included in the range, but it is not equal to the range,
1296
 *  <code>false</code> otherwise.
1297
 *  Raises +TypeError+ if +obj+ is not a Range.
1298
 *
1299
 *     ("b".."e").strict_superset?("b".."d") #=> true
1300
 *     ("b".."e").strict_superset?("b".."e") #=> false
1301
 *     ("b".."e").strict_superset?("a".."e") #=> false
1302
 */
1303

  
1304
static VALUE
1305
range_strict_superset(VALUE range, VALUE obj)
1306
{
1307
    if (!rb_obj_is_kind_of(obj, rb_cRange))
1308
        rb_raise(rb_eTypeError, "not a range object");
1309

  
1310
    return range_strict_subset(obj, range);
1311
}
1312

  
1204 1313
static VALUE
1205 1314
range_dumper(VALUE range)
1206 1315
{
......
1310 1419
    id_excl = rb_intern("excl");
1311 1420
    id_integer_p = rb_intern("integer?");
1312 1421
    id_div = rb_intern("div");
1422
    id_min = rb_intern("min");
1423
    id_max = rb_intern("max");
1313 1424

  
1314 1425
    rb_cRange = rb_struct_define_without_accessor(
1315 1426
        "Range", rb_cObject, range_alloc,
......
1341 1452
    rb_define_method(rb_cRange, "member?", range_include, 1);
1342 1453
    rb_define_method(rb_cRange, "include?", range_include, 1);
1343 1454
    rb_define_method(rb_cRange, "cover?", range_cover, 1);
1455

  
1456
    rb_define_method(rb_cRange, "subset?", range_subset, 1);
1457
    rb_define_method(rb_cRange, "<=", range_subset, 1);
1458
    rb_define_method(rb_cRange, "strict_subset?", range_strict_subset, 1);
1459
    rb_define_method(rb_cRange, "<", range_strict_subset, 1);
1460

  
1461
    rb_define_method(rb_cRange, "superset?", range_superset, 1);
1462
    rb_define_method(rb_cRange, ">=", range_superset, 1);
1463
    rb_define_method(rb_cRange, "strict_superset?", range_strict_superset, 1);
1464
    rb_define_method(rb_cRange, ">", range_strict_superset, 1);
1344 1465
}
test/ruby/test_range.rb
379 379
    assert_operator("a".."z", :cover?, "cc")
380 380
  end
381 381

  
382
  def test_subset
383
    [:subset?, :<=].each do |op|
384
      assert_operator("b".."e", op, "b".."e")
385
      assert_operator("b".."e", op, "b"..."f")
386
      assert_operator("b"..."f", op, "b".."e")
387
      assert_operator("b".."d", op, "b".."e")
388
      assert_operator("c".."e", op, "b".."e")
389
      assert_operator("c".."d", op, "b".."e")
390
      assert_operator("g".."f", op, "b".."e")
391
      assert_operator("c".."b", op, "d".."a")
392

  
393
      assert_not_operator("a".."e", op, "b".."e")
394
      assert_not_operator("a".."e", op, "b"..."f")
395
      assert_not_operator("a"..."f", op, "b".."e")
396
      assert_not_operator("b".."f", op, "b".."e")
397
      assert_not_operator("a".."f", op, "b".."e")
398

  
399
      assert_raise(TypeError) { ("a".."c").send(op, "x") }
400
    end
401
  end
402

  
403
  def test_strict_subset
404
    [:strict_subset?, :<].each do |op|
405
      assert_operator("b".."d", op, "b".."e")
406
      assert_operator("b".."d", op, "b"..."f")
407
      assert_operator("b"..."e", op, "b".."e")
408
      assert_operator("c".."e", op, "b".."e")
409
      assert_operator("c".."d", op, "b".."e")
410
      assert_operator("g".."f", op, "b".."e")
411

  
412
      assert_not_operator("b".."e", op, "b".."e")
413
      assert_not_operator("b".."e", op, "b"..."f")
414
      assert_not_operator("b"..."f", op, "b".."e")
415
      assert_not_operator("a".."e", op, "b".."e")
416
      assert_not_operator("b".."f", op, "b".."e")
417
      assert_not_operator("a".."f", op, "b".."e")
418
      assert_not_operator("c".."b", op, "d".."a")
419

  
420
      assert_raise(TypeError) { ("a".."c").send(op, "x") }
421
    end
422
  end
423

  
424
  def test_superset
425
    [:superset?, :>=].each do |op|
426
      assert_operator("b".."e", op, "b".."e")
427
      assert_operator("b".."e", op, "b"..."f")
428
      assert_operator("b"..."f", op, "b".."e")
429
      assert_operator("b".."e", op, "b".."d")
430
      assert_operator("b".."e", op, "c".."e")
431
      assert_operator("b".."e", op, "c".."d")
432
      assert_operator("b".."e", op, "g".."f")
433
      assert_operator("d".."a", op, "c".."b")
434

  
435
      assert_not_operator("b".."e", op, "a".."e")
436
      assert_not_operator("b".."e", op, "a"..."f")
437
      assert_not_operator("b"..."f", op, "a".."e")
438
      assert_not_operator("b".."e", op, "b".."f")
439
      assert_not_operator("b".."e", op, "a".."f")
440
      assert_not_operator("b".."e", op, "b".."f")
441
      assert_not_operator("b".."e", op, "a".."f")
442

  
443
      assert_raise(TypeError) { ("a".."c").send(op, "x") }
444
    end
445
  end
446

  
447
  def test_strict_superset
448
    [:strict_superset?, :>].each do |op|
449
      assert_operator("b".."e", op, "b".."d")
450
      assert_operator("b".."e", op, "b"..."e")
451
      assert_operator("b"..."f", op, "b".."d")
452
      assert_operator("b".."e", op, "c".."e")
453
      assert_operator("b".."e", op, "c".."d")
454
      assert_operator("b".."e", op, "g".."f")
455

  
456
      assert_not_operator("b".."e", op, "b".."e")
457
      assert_not_operator("b".."e", op, "b"..."f")
458
      assert_not_operator("b"..."f", op, "b".."e")
459
      assert_not_operator("b".."e", op, "a".."e")
460
      assert_not_operator("b".."e", op, "b".."f")
461
      assert_not_operator("b".."e", op, "a".."f")
462
      assert_not_operator("d".."a", op, "c".."b")
463

  
464
      assert_raise(TypeError) { ("a".."c").send(op, "x") }
465
    end
466
  end
467

  
382 468
  def test_beg_len
383 469
    o = Object.new
384 470
    assert_raise(TypeError) { [][o] }
385
-