Skip to content

Commit db5ebf2

Browse files
committed
CHANGE: FIND bitset! block! is looking for ALL of the values in the block by default
resolves: Oldes/Rebol-issues#1512
1 parent 458f599 commit db5ebf2

File tree

2 files changed

+97
-15
lines changed

2 files changed

+97
-15
lines changed

src/core/t-bitset.c

+65-15
Original file line numberDiff line numberDiff line change
@@ -236,9 +236,10 @@
236236

237237
/***********************************************************************
238238
**
239-
*/ REBFLG Check_Bit_Str(REBSER *bset, REBVAL *val, REBFLG uncased)
239+
*/ REBFLG Check_Bit_Str_Any(REBSER *bset, REBVAL *val, REBFLG uncased)
240240
/*
241241
** If uncased is TRUE, try to match either upper or lower case.
242+
** Returns TRUE when first bit is found.
242243
**
243244
***********************************************************************/
244245
{
@@ -257,6 +258,30 @@
257258
return FALSE;
258259
}
259260

261+
/***********************************************************************
262+
**
263+
*/ REBFLG Check_Bit_Str_All(REBSER *bset, REBVAL *val, REBFLG uncased)
264+
/*
265+
** If uncased is TRUE, try to match either upper or lower case.
266+
** Returns TRUE when all bits are found.
267+
**
268+
***********************************************************************/
269+
{
270+
REBCNT n = VAL_INDEX(val);
271+
272+
if (VAL_BYTE_SIZE(val)) {
273+
REBYTE *bp = VAL_BIN(val);
274+
for (; n < VAL_TAIL(val); n++)
275+
if (!Check_Bit(bset, bp[n], uncased)) return FALSE;
276+
}
277+
else {
278+
REBUNI *up = VAL_UNI(val);
279+
for (; n < VAL_TAIL(val); n++)
280+
if (!Check_Bit(bset, up[n], uncased)) return FALSE;
281+
}
282+
return TRUE;
283+
}
284+
260285

261286
/***********************************************************************
262287
**
@@ -414,10 +439,11 @@
414439

415440
/***********************************************************************
416441
**
417-
*/ REBFLG Check_Bits(REBSER *bset, REBVAL *val, REBFLG uncased)
442+
*/ REBFLG Check_Bits(REBSER *bset, REBVAL *val, REBFLG uncased, REBFLG any)
418443
/*
419444
** Check bits indicated by strings and chars and ranges.
420445
** If uncased is TRUE, try to match either upper or lower case.
446+
** If any is TRUE, than returns TRUE on first found bit.
421447
**
422448
***********************************************************************/
423449
{
@@ -430,8 +456,15 @@
430456
if (IS_INTEGER(val))
431457
return Check_Bit(bset, Int32s(val, 0), uncased);
432458

433-
if (ANY_BINSTR(val))
434-
return Check_Bit_Str(bset, val, uncased);
459+
if (ANY_BINSTR(val)) {
460+
if (any) {
461+
return Check_Bit_Str_Any(bset, val, uncased);
462+
}
463+
else {
464+
return Check_Bit_Str_All(bset, val, uncased);
465+
}
466+
467+
}
435468

436469
if (!ANY_BLOCK(val)) Trap_Type(val);
437470

@@ -448,17 +481,24 @@
448481
n = VAL_CHAR(val);
449482
scan_bits:
450483
if (n < c) Trap1(RE_PAST_END, val);
451-
for (; c <= n; c++)
452-
if (Check_Bit(bset, c, uncased)) goto found;
484+
if (any) {
485+
for (; c <= n; c++)
486+
if (Check_Bit(bset, c, uncased)) return TRUE;
487+
}
488+
else {
489+
for (; c <= n; c++)
490+
if (!Check_Bit(bset, c, uncased)) return FALSE;
491+
goto bit_found;
492+
}
453493
} else Trap_Arg(val);
454494
}
455495
else
456-
if (Check_Bit(bset, c, uncased)) goto found;
496+
if (Check_Bit(bset, c, uncased)) goto bit_found;
457497
break;
458498

459499
case REB_INTEGER:
460500
n = Int32s(val, 0);
461-
if (n > 0xffff) return 0;
501+
if (n > 0xffff) goto bit_not_found;
462502
if (IS_SAME_WORD(val + 1, SYM__)) {
463503
c = n;
464504
val += 2;
@@ -468,7 +508,7 @@
468508
} else Trap_Arg(val);
469509
}
470510
else
471-
if (Check_Bit(bset, n, uncased)) goto found;
511+
if (Check_Bit(bset, n, uncased)) goto bit_found;
472512
break;
473513

474514
case REB_BINARY:
@@ -478,16 +518,26 @@
478518
case REB_URL:
479519
case REB_TAG:
480520
// case REB_ISSUE:
481-
if (Check_Bit_Str(bset, val, uncased)) goto found;
521+
if (any) {
522+
if (Check_Bit_Str_Any(bset, val, uncased)) goto bit_found;
523+
}
524+
else {
525+
if (Check_Bit_Str_All(bset, val, uncased)) goto bit_found;
526+
}
482527
break;
483528

484529
default:
485530
Trap_Type(val);
486531
}
532+
bit_not_found:
533+
if (!any)
534+
return FALSE;
535+
continue;
536+
bit_found:
537+
if (any) {
538+
return TRUE;
539+
}
487540
}
488-
return FALSE;
489-
490-
found:
491541
return TRUE;
492542
}
493543

@@ -511,7 +561,7 @@
511561
}
512562
return PE_NONE;
513563
#else
514-
SET_LOGIC(pvs->store, Check_Bits(ser, pvs->select, 0));
564+
SET_LOGIC(pvs->store, Check_Bits(ser, pvs->select, 0, FALSE));
515565
return PE_USE;
516566
#endif
517567
}
@@ -600,7 +650,7 @@
600650

601651
case A_PICK:
602652
case A_FIND:
603-
if (!Check_Bits(VAL_SERIES(value), arg,(IS_CHAR(arg) && action == A_FIND && !D_REF(ARG_FIND_CASE)) ))
653+
if (!Check_Bits(VAL_SERIES(value), arg,(IS_CHAR(arg) && action == A_FIND && !D_REF(ARG_FIND_CASE)), (action == A_FIND && D_REF(ARG_FIND_ANY))))
604654
#ifdef PICK_BITSET_AS_NONE
605655
return R_NONE;
606656
#else

src/tests/units/bitset-test.r3

+32
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,11 @@
142142
--assert bs/8 = true
143143
--assert bs/9 = false
144144

145+
--test-- "pick-9"
146+
ABC: charset [#"A" #"B" #"C"]
147+
--assert pick ABC "BCB"
148+
--assert not pick ABC "BCBX"
149+
145150
===end-group===
146151

147152
===start-group=== "modify"
@@ -223,6 +228,33 @@
223228
--assert pick ABC #"A"
224229
--assert not pick ABC #"a"
225230

231+
--test-- "find bitset! string!"
232+
--assert find ABC "ABC"
233+
--assert find ABC "BAC"
234+
--assert find ABC "CA"
235+
--assert find/any ABC "XCA"
236+
--assert not find ABC "XCA"
237+
--assert not find ABC "abc" ;@@ should be searching of a string case-insensitive?
238+
239+
--test-- "find bitset! block-of-integers"
240+
;@@ https://github.com/Oldes/Rebol-issues/issues/1512
241+
bits1-3: make bitset! [1 - 3]
242+
--assert find bits1-3 [1]
243+
--assert find bits1-3 [1 2]
244+
--assert find bits1-3 [1 - 3]
245+
--assert find bits1-3 as paren! [1 - 3]
246+
--assert not find bits1-3 [4]
247+
--assert not find bits1-3 [1 2 4]
248+
--assert not find bits1-3 [1 - 4]
249+
--assert find/any bits1-3 [4 1]
250+
--assert find/any bits1-3 [1 2 4]
251+
--assert find/any bits1-3 [1 - 4]
252+
253+
--test-- "find bitset! block-of-strings!"
254+
--assert find ABC ["AB"]
255+
--assert find ABC ["AB" "CB"]
256+
--assert not find ABC ["AB" "CBX"]
257+
226258
===end-group===
227259

228260

0 commit comments

Comments
 (0)