static REBCNT find_string(REBSER *series, REBCNT index, REBCNT end, REBVAL *target, REBCNT len, REBCNT flags, REBINT skip) { REBCNT start = index; if (flags & (AM_FIND_REVERSE | AM_FIND_LAST)) { skip = -1; start = 0; if (flags & AM_FIND_LAST) index = end - len; else index--; } if (ANY_BINSTR(target)) { // Do the optimal search or the general search? if (BYTE_SIZE(series) && VAL_BYTE_SIZE(target) && !(flags & ~(AM_FIND_CASE|AM_FIND_MATCH))) return Find_Byte_Str(series, start, VAL_BIN_DATA(target), len, !GET_FLAG(flags, ARG_FIND_CASE-1), GET_FLAG(flags, ARG_FIND_MATCH-1)); else return Find_Str_Str(series, start, index, end, skip, VAL_SERIES(target), VAL_INDEX(target), len, flags & (AM_FIND_MATCH|AM_FIND_CASE)); } else if (IS_BINARY(target)) { return Find_Byte_Str(series, start, VAL_BIN_DATA(target), len, 0, GET_FLAG(flags, ARG_FIND_MATCH-1)); } else if (IS_CHAR(target)) { return Find_Str_Char(series, start, index, end, skip, VAL_CHAR(target), flags); } else if (IS_INTEGER(target)) { return Find_Str_Char(series, start, index, end, skip, (REBUNI)VAL_INT32(target), flags); } else if (IS_BITSET(target)) { return Find_Str_Bitset(series, start, index, end, skip, VAL_SERIES(target), flags); } return NOT_FOUND; }
// // Xandor_Binary: C // // Only valid for BINARY data. // REBSER *Xandor_Binary(const REBVAL *verb, REBVAL *value, REBVAL *arg) { REBYTE *p0 = VAL_BIN_AT(value); REBYTE *p1 = VAL_BIN_AT(arg); REBCNT t0 = VAL_LEN_AT(value); REBCNT t1 = VAL_LEN_AT(arg); REBCNT mt = MIN(t0, t1); // smaller array size // !!! This used to say "For AND - result is size of shortest input:" but // the code was commented out /* if (verb == A_AND || (verb == 0 && t1 >= t0)) t2 = mt; else t2 = MAX(t0, t1); */ REBCNT t2 = MAX(t0, t1); REBSER *series; if (IS_BITSET(value)) { // // Although bitsets and binaries share some implementation here, // they have distinct allocation functions...and bitsets need // to set the REBSER.misc.negated union field (BITS_NOT) as // it would be illegal to read it if it were cleared via another // element of the union. // assert(IS_BITSET(arg)); series = Make_Bitset(t2 * 8); } else { // Ordinary binary // series = Make_Binary(t2); TERM_SEQUENCE_LEN(series, t2); } REBYTE *p2 = BIN_HEAD(series); switch (VAL_WORD_SYM(verb)) { case SYM_INTERSECT: { // and REBCNT i; for (i = 0; i < mt; i++) *p2++ = *p0++ & *p1++; CLEAR(p2, t2 - mt); return series; } case SYM_UNION: { // or REBCNT i; for (i = 0; i < mt; i++) *p2++ = *p0++ | *p1++; break; } case SYM_DIFFERENCE: { // xor REBCNT i; for (i = 0; i < mt; i++) *p2++ = *p0++ ^ *p1++; break; } case SYM_EXCLUDE: { // !!! not a "type action", word manually in %words.r REBCNT i; for (i = 0; i < mt; i++) *p2++ = *p0++ & ~*p1++; if (t0 > t1) memcpy(p2, p0, t0 - t1); // residual from first only return series; } default: fail (Error_Cannot_Use_Raw(verb, Datatype_From_Kind(REB_BINARY))); } // Copy the residual // memcpy(p2, ((t0 > t1) ? p0 : p1), t2 - mt); return series; }
// // Xandor_Binary: C // // Only valid for BINARY data. // REBSER *Xandor_Binary(REBCNT action, REBVAL *value, REBVAL *arg) { REBSER *series; REBYTE *p0 = VAL_BIN_AT(value); REBYTE *p1 = VAL_BIN_AT(arg); REBYTE *p2; REBCNT i; REBCNT mt, t1, t0, t2; t0 = VAL_LEN_AT(value); t1 = VAL_LEN_AT(arg); mt = MIN(t0, t1); // smaller array size // For AND - result is size of shortest input: // if (action == A_AND || (action == 0 && t1 >= t0)) // t2 = mt; // else t2 = MAX(t0, t1); if (IS_BITSET(value)) { // // Although bitsets and binaries share some implementation here, // they have distinct allocation functions...and bitsets need // to set the REBSER.misc.negated union field (BITS_NOT) as // it would be illegal to read it if it were cleared via another // element of the union. // assert(IS_BITSET(arg)); series = Make_Bitset(t2 * 8); } else { // Ordinary binary // series = Make_Binary(t2); SET_SERIES_LEN(series, t2); } p2 = BIN_HEAD(series); switch (action) { case SYM_AND_T: // and~ for (i = 0; i < mt; i++) *p2++ = *p0++ & *p1++; CLEAR(p2, t2 - mt); return series; case SYM_OR_T: // or~ for (i = 0; i < mt; i++) *p2++ = *p0++ | *p1++; break; case SYM_XOR_T: // xor~ for (i = 0; i < mt; i++) *p2++ = *p0++ ^ *p1++; break; default: // special bit set case EXCLUDE: for (i = 0; i < mt; i++) *p2++ = *p0++ & ~*p1++; if (t0 > t1) memcpy(p2, p0, t0 - t1); // residual from first only return series; } // Copy the residual: memcpy(p2, ((t0 > t1) ? p0 : p1), t2 - mt); return series; }
static REBCNT find_string( REBSER *series, REBCNT index, REBCNT end, REBVAL *target, REBCNT target_len, REBCNT flags, REBINT skip ) { assert(end >= index); if (target_len > end - index) // series not long enough to have target return NOT_FOUND; REBCNT start = index; if (flags & (AM_FIND_REVERSE | AM_FIND_LAST)) { skip = -1; start = 0; if (flags & AM_FIND_LAST) index = end - target_len; else index--; } if (ANY_BINSTR(target)) { // Do the optimal search or the general search? if ( BYTE_SIZE(series) && VAL_BYTE_SIZE(target) && !(flags & ~(AM_FIND_CASE|AM_FIND_MATCH)) ) { return Find_Byte_Str( series, start, VAL_BIN_AT(target), target_len, NOT(GET_FLAG(flags, ARG_FIND_CASE - 1)), GET_FLAG(flags, ARG_FIND_MATCH - 1) ); } else { return Find_Str_Str( series, start, index, end, skip, VAL_SERIES(target), VAL_INDEX(target), target_len, flags & (AM_FIND_MATCH|AM_FIND_CASE) ); } } else if (IS_BINARY(target)) { const REBOOL uncase = FALSE; return Find_Byte_Str( series, start, VAL_BIN_AT(target), target_len, uncase, // "don't treat case insensitively" GET_FLAG(flags, ARG_FIND_MATCH - 1) ); } else if (IS_CHAR(target)) { return Find_Str_Char( VAL_CHAR(target), series, start, index, end, skip, flags ); } else if (IS_INTEGER(target)) { return Find_Str_Char( cast(REBUNI, VAL_INT32(target)), series, start, index, end, skip, flags ); } else if (IS_BITSET(target)) { return Find_Str_Bitset( series, start, index, end, skip, VAL_SERIES(target), flags ); } return NOT_FOUND; }