Project

General

Profile

Feature #14473 ยป v3-0001-range.c-add-subrange-superrange-methods.patch

owst (Owen Stephens), 03/25/2018 03:55 PM

View differences:

range.c
18 18
#include <math.h>
19 19
VALUE rb_cRange;
20
static ID id_beg, id_end, id_excl, id_integer_p, id_div;
20
static ID id_beg, id_end, id_excl, id_integer_p, id_div, id_min, id_max;
21 21
#define id_cmp idCmp
22 22
#define id_succ idSucc
......
1202 1202
}
1203 1203
static VALUE
1204
r_cover_min_and_max_p(VALUE range, VALUE obj, VALUE (*func)(VALUE, VALUE, VALUE))
1205
{
1206
    if (!rb_obj_is_kind_of(obj, rb_cRange))
1207
        rb_raise(rb_eTypeError, "not a range object");
1208

  
1209
    VALUE range_min = rb_funcall(range, id_min, 0);
1210

  
1211
    if (range_min == Qnil)
1212
        return Qfalse;
1213

  
1214
    VALUE range_max = rb_funcall(range, id_max, 0);
1215

  
1216
    if (range_cover(obj, range_min) &&
1217
        range_cover(obj, range_max) &&
1218
        (!func || (*func)(obj, range_min, range_max))) {
1219
    return Qtrue;
1220
    }
1221
    return Qfalse;
1222
}
1223

  
1224
/*
1225
 *  call-seq:
1226
 *     rng.subrange?(obj)  ->  true or false
1227
 *
1228
 *  Returns <code>true</code> if +obj+ is a Range and it covers the min and max
1229
 *  elements of the range, <code>false</code> otherwise.
1230
 *  Raises +TypeError+ if +obj+ is not a Range.
1231
 *
1232
 *     ("b".."d").subrange?("b".."e") #=> true
1233
 *     ("b".."e").subrange?("b".."e") #=> true
1234
 *     ("a".."e").subrange?("b".."e") #=> false
1235
 */
1236

  
1237
static VALUE
1238
range_subrange(VALUE range, VALUE obj)
1239
{
1240
    return r_cover_min_and_max_p(range, obj, NULL);
1241
}
1242

  
1243
#define DIFFER_AT(recv, mid, val) (!rb_equal(rb_funcall(recv, mid, 0), val))
1244

  
1245
static VALUE
1246
r_min_or_max_differ(VALUE obj, VALUE min, VALUE max)
1247
{
1248
   return DIFFER_AT(obj, id_min, min) || DIFFER_AT(obj, id_max, max);
1249
}
1250

  
1251
/*
1252
 *  call-seq:
1253
 *     rng.strict_subrange?(obj)  ->  true or false
1254
 *
1255
 *  Returns <code>true</code> if +obj+ is a Range and it covers the min and max
1256
 *  elements of the range and the ranges differ in their min or max elements,
1257
 *  <code>false</code> otherwise.
1258
 *  Raises +TypeError+ if +obj+ is not a Range.
1259
 *
1260
 *     ("b".."d").strict_subrange?("b".."e") #=> true
1261
 *     ("b".."e").strict_subrange?("b".."e") #=> false
1262
 *     ("a".."e").strict_subrange?("b".."e") #=> false
1263
 */
1264

  
1265
static VALUE
1266
range_strict_subrange(VALUE range, VALUE obj)
1267
{
1268
    return r_cover_min_and_max_p(range, obj, &r_min_or_max_differ);
1269
}
1270

  
1271
/*
1272
 *  call-seq:
1273
 *     rng.superrange?(obj)  ->  true or false
1274
 *
1275
 *  Returns <code>true</code> if +obj+ is a Range and its min and max elements
1276
 *  are covered by the range, <code>false</code> otherwise.
1277
 *  Raises +TypeError+ if +obj+ is not a Range.
1278
 *
1279
 *     ("b".."e").superrange?("b".."d") #=> true
1280
 *     ("b".."e").superrange?("b".."e") #=> true
1281
 *     ("b".."e").superrange?("a".."e") #=> false
1282
 */
1283

  
1284
static VALUE
1285
range_superrange(VALUE range, VALUE obj)
1286
{
1287
    if (!rb_obj_is_kind_of(obj, rb_cRange))
1288
        rb_raise(rb_eTypeError, "not a range object");
1289

  
1290
    return range_subrange(obj, range);
1291
}
1292

  
1293
/*
1294
 *  call-seq:
1295
 *     rng.strict_superrange?(obj)  ->  true or false
1296
 *
1297
 *  Returns <code>true</code> if +obj+ is a Range and its min and max elements
1298
 *  are covered by the range and the ranges differ in their min or max
1299
 *  elements, <code>false</code> otherwise.
1300
 *  Raises +TypeError+ if +obj+ is not a Range.
1301
 *
1302
 *     ("b".."e").strict_superrange?("b".."d") #=> true
1303
 *     ("b".."e").strict_superrange?("b".."e") #=> false
1304
 *     ("b".."e").strict_superrange?("a".."e") #=> false
1305
 */
1306

  
1307
static VALUE
1308
range_strict_superrange(VALUE range, VALUE obj)
1309
{
1310
    if (!rb_obj_is_kind_of(obj, rb_cRange))
1311
        rb_raise(rb_eTypeError, "not a range object");
1312

  
1313
    return range_strict_subrange(obj, range);
1314
}
1315

  
1316
static VALUE
1204 1317
range_dumper(VALUE range)
1205 1318
{
1206 1319
    VALUE v;
......
1310 1423
    id_excl = rb_intern("excl");
1311 1424
    id_integer_p = rb_intern("integer?");
1312 1425
    id_div = rb_intern("div");
1426
    id_min = rb_intern("min");
1427
    id_max = rb_intern("max");
1313 1428
    rb_cRange = rb_struct_define_without_accessor(
1314 1429
        "Range", rb_cObject, range_alloc,
......
1341 1456
    rb_define_method(rb_cRange, "member?", range_include, 1);
1342 1457
    rb_define_method(rb_cRange, "include?", range_include, 1);
1343 1458
    rb_define_method(rb_cRange, "cover?", range_cover, 1);
1459

  
1460
    rb_define_method(rb_cRange, "subrange?", range_subrange, 1);
1461
    rb_define_method(rb_cRange, "strict_subrange?", range_strict_subrange, 1);
1462
    rb_define_method(rb_cRange, "superrange?", range_superrange, 1);
1463
    rb_define_method(rb_cRange, "strict_superrange?", range_strict_superrange, 1);
1344 1464
}
test/ruby/test_range.rb
379 379
    assert_operator("a".."z", :cover?, "cc")
380 380
  end
381
  def test_subrange
382
    assert_operator("b".."e", :subrange?, "b".."e")
383
    assert_operator("b".."e", :subrange?, "b"..."f")
384
    assert_operator("b"..."f", :subrange?, "b".."e")
385
    assert_operator("b".."d", :subrange?, "b".."e")
386
    assert_operator("c".."e", :subrange?, "b".."e")
387
    assert_operator("c".."d", :subrange?, "b".."e")
388

  
389
    assert_not_operator("a".."e", :subrange?, "b".."e")
390
    assert_not_operator("a".."e", :subrange?, "b"..."f")
391
    assert_not_operator("a"..."f", :subrange?, "b".."e")
392
    assert_not_operator("b".."f", :subrange?, "b".."e")
393
    assert_not_operator("a".."f", :subrange?, "b".."e")
394
    assert_not_operator("g".."f", :subrange?, "b".."e")
395
    assert_not_operator("b".."c", :subrange?, "d".."a")
396
    assert_not_operator("c".."b", :subrange?, "d".."a")
397

  
398
    assert_raise(TypeError) { ("a".."c").subrange?("x") }
399
  end
400

  
401
  def test_strict_subrange
402
    assert_operator("b".."d", :strict_subrange?, "b".."e")
403
    assert_operator("b".."d", :strict_subrange?, "b"..."f")
404
    assert_operator("b"..."e", :strict_subrange?, "b".."e")
405

  
406
    assert_not_operator("b".."e", :strict_subrange?, "b".."e")
407
    assert_not_operator("b".."e", :strict_subrange?, "b"..."f")
408
    assert_not_operator("b"..."f", :strict_subrange?, "b".."e")
409
    assert_not_operator("a".."e", :strict_subrange?, "b".."e")
410
    assert_not_operator("b".."f", :strict_subrange?, "b".."e")
411
    assert_not_operator("a".."f", :strict_subrange?, "b".."e")
412
    assert_not_operator("g".."f", :strict_subrange?, "b".."e")
413
    assert_not_operator("b".."c", :strict_subrange?, "d".."a")
414
    assert_not_operator("c".."b", :strict_subrange?, "d".."a")
415

  
416
    assert_raise(TypeError) { ("a".."c").strict_subrange?("x") }
417
  end
418

  
419
  def test_superrange
420
    assert_operator("b".."e", :superrange?, "b".."e")
421
    assert_operator("b".."e", :superrange?, "b"..."f")
422
    assert_operator("b"..."f", :superrange?, "b".."e")
423
    assert_operator("b".."e", :superrange?, "b".."d")
424
    assert_operator("b".."e", :superrange?, "c".."e")
425
    assert_operator("b".."e", :superrange?, "c".."d")
426

  
427
    assert_not_operator("b".."e", :superrange?, "a".."e")
428
    assert_not_operator("b".."e", :superrange?, "a"..."f")
429
    assert_not_operator("b"..."f", :superrange?, "a".."e")
430
    assert_not_operator("b".."e", :superrange?, "b".."f")
431
    assert_not_operator("b".."e", :superrange?, "a".."f")
432
    assert_not_operator("b".."e", :superrange?, "b".."f")
433
    assert_not_operator("b".."e", :superrange?, "a".."f")
434
    assert_not_operator("b".."e", :subrange?, "g".."f")
435
    assert_not_operator("d".."a", :subrange?, "b".."c")
436
    assert_not_operator("d".."a", :subrange?, "c".."b")
437

  
438
    assert_raise(TypeError) { ("a".."c").superrange?("x") }
439
  end
440

  
441
  def test_strict_superrange
442
    assert_operator("b".."e", :strict_superrange?, "b".."d")
443
    assert_operator("b".."e", :strict_superrange?, "b"..."e")
444
    assert_operator("b"..."f", :strict_superrange?, "b".."d")
445
    assert_operator("b".."e", :strict_superrange?, "c".."e")
446
    assert_operator("b".."e", :strict_superrange?, "c".."d")
447

  
448
    assert_not_operator("b".."e", :strict_superrange?, "b".."e")
449
    assert_not_operator("b".."e", :strict_superrange?, "b"..."f")
450
    assert_not_operator("b"..."f", :strict_superrange?, "b".."e")
451
    assert_not_operator("b".."e", :strict_superrange?, "a".."e")
452
    assert_not_operator("b".."e", :strict_superrange?, "b".."f")
453
    assert_not_operator("b".."e", :strict_superrange?, "a".."f")
454
    assert_not_operator("b".."e", :strict_subrange?, "g".."f")
455
    assert_not_operator("d".."a", :strict_subrange?, "b".."c")
456
    assert_not_operator("d".."a", :strict_subrange?, "c".."b")
457

  
458
    assert_raise(TypeError) { ("a".."c").strict_superrange?("x") }
459
  end
460

  
381 461
  def test_beg_len
382 462
    o = Object.new
383 463
    assert_raise(TypeError) { [][o] }
384
-