// // Complement_Binary: C // // Only valid for BINARY data. // REBSER *Complement_Binary(REBVAL *value) { const REBYTE *bp = VAL_BIN_AT(value); REBCNT len = VAL_LEN_AT(value); REBSER *bin = Make_Binary(len); TERM_SEQUENCE_LEN(bin, len); REBYTE *dp = BIN_HEAD(bin); for (; len > 0; len--, ++bp, ++dp) *dp = ~(*bp); return bin; }
// // 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; }
static REBSER *make_binary(const REBVAL *arg, REBOOL make) { REBSER *ser; // MAKE BINARY! 123 switch (VAL_TYPE(arg)) { case REB_INTEGER: case REB_DECIMAL: if (make) ser = Make_Binary(Int32s(arg, 0)); else ser = Make_Binary_BE64(arg); break; // MAKE/TO BINARY! BINARY! case REB_BINARY: ser = Copy_Bytes(VAL_BIN_AT(arg), VAL_LEN_AT(arg)); break; // MAKE/TO BINARY! <any-string> case REB_STRING: case REB_FILE: case REB_EMAIL: case REB_URL: case REB_TAG: // case REB_ISSUE: ser = Make_UTF8_From_Any_String(arg, VAL_LEN_AT(arg), 0); break; case REB_BLOCK: // Join_Binary returns a shared buffer, so produce a copy: ser = Copy_Sequence(Join_Binary(arg, -1)); break; // MAKE/TO BINARY! <tuple!> case REB_TUPLE: ser = Copy_Bytes(VAL_TUPLE(arg), VAL_TUPLE_LEN(arg)); break; // MAKE/TO BINARY! <char!> case REB_CHAR: ser = Make_Binary(6); TERM_SEQUENCE_LEN(ser, Encode_UTF8_Char(BIN_HEAD(ser), VAL_CHAR(arg))); break; // MAKE/TO BINARY! <bitset!> case REB_BITSET: ser = Copy_Bytes(VAL_BIN(arg), VAL_LEN_HEAD(arg)); break; // MAKE/TO BINARY! <image!> case REB_IMAGE: ser = Make_Image_Binary(arg); break; case REB_MONEY: ser = Make_Binary(12); deci_to_binary(BIN_HEAD(ser), VAL_MONEY_AMOUNT(arg)); TERM_SEQUENCE_LEN(ser, 12); break; default: ser = 0; } return ser; }