コード例 #1
0
ファイル: t-tuple.c プロジェクト: 51weekend/r3
*/	REBFLG MT_Tuple(REBVAL *out, REBVAL *data, REBCNT type)
/*
***********************************************************************/
{
	REBYTE	*vp;
	REBINT len = 0;
	REBINT n;

	vp = VAL_TUPLE(out);
	for (; NOT_END(data); data++, vp++, len++) {
		if (len >= 10) return FALSE;
		if (IS_INTEGER(data)) {
			n = Int32(data);
		}
		else if (IS_CHAR(data)) {
			n = VAL_CHAR(data);
		}
		else return FALSE;
		if (n > 255 || n < 0) return FALSE;
		*vp = n;
	}

	VAL_TUPLE_LEN(out) = len;

	for (; len < 10; len++) *vp++ = 0;

	VAL_SET(out, type);
	return TRUE;
}
コード例 #2
0
ファイル: t-tuple.c プロジェクト: 51weekend/r3
*/  REBINT Emit_Tuple(REBVAL *value, REBYTE *out)
/*
**		The out array must be large enough to hold longest tuple.
**		Longest is: (3 digits + '.') * 11 nums + 1 term => 45
**
***********************************************************************/
{
	REBCNT len;
	REBYTE *tp;
	REBYTE *start = out;

	len = VAL_TUPLE_LEN(value);
	tp = (REBYTE *)VAL_TUPLE(value);
	for (; len > 0; len--, tp++) {
		out = Form_Int(out, *tp);
		*out++ = '.';
	}

	len = VAL_TUPLE_LEN(value);
	while (len++ < 3) {
		*out++ = '0';
		*out++ = '.';
	}
	*--out = 0;

	return out-start;
}
コード例 #3
0
ファイル: t-tuple.c プロジェクト: hostilefork/rebol
//
//  Cmp_Tuple: C
//
// Given two tuples, compare them.
//
REBINT Cmp_Tuple(const RELVAL *t1, const RELVAL *t2)
{
    REBCNT  len;
    const REBYTE *vp1, *vp2;
    REBINT  n;

    len = MAX(VAL_TUPLE_LEN(t1), VAL_TUPLE_LEN(t2));
    vp1 = VAL_TUPLE(t1);
    vp2 = VAL_TUPLE(t2);

    for (; len > 0; len--, vp1++,vp2++) {
        n = (REBINT)(*vp1 - *vp2);
        if (n != 0)
            return n;
    }
    return 0;
}
コード例 #4
0
ファイル: f-stubs.c プロジェクト: kjanz1899/ren-c
//
//  Set_Tuple: C
//
void Set_Tuple(REBVAL *value, REBYTE *bytes, REBCNT len)
{
    REBYTE *bp;

    VAL_RESET_HEADER(value, REB_TUPLE);
    VAL_TUPLE_LEN(value) = (REBYTE)len;
    for (bp = VAL_TUPLE(value); len > 0; len--)
        *bp++ = *bytes++;
}
コード例 #5
0
ファイル: t-tuple.c プロジェクト: hostilefork/rebol
//
//  Cmp_Tuple: C
//
// Given two tuples, compare them.
//
REBINT Cmp_Tuple(const REBCEL *t1, const REBCEL *t2)
{
    REBCNT len = MAX(VAL_TUPLE_LEN(t1), VAL_TUPLE_LEN(t2));
    assert(len < MAX_TUPLE);

    const REBYTE *vp1 = VAL_TUPLE(t1);
    const REBYTE *vp2 = VAL_TUPLE(t2);

    // Note: unused bytes in tuples are 0, so that 1.0.0 can = 1.0.0.0

    REBINT n;
    for (; len > 0; len--, ++vp1, ++vp2) {
        n = cast(REBINT, *vp1) - *vp2;
        if (n != 0)
            return n;
    }
    return 0;
}
コード例 #6
0
ファイル: f-stubs.c プロジェクト: 51weekend/r3
*/	void Set_Tuple(REBVAL *value, REBYTE *bytes, REBCNT len)
/*
***********************************************************************/
{
	REBYTE *bp;

	VAL_SET(value, REB_TUPLE);
	VAL_TUPLE_LEN(value) = (REBYTE)len;
	for (bp = VAL_TUPLE(value); len > 0; len--)
		*bp++ = *bytes++;
}
コード例 #7
0
ファイル: t-tuple.c プロジェクト: 51weekend/r3
*/	REBINT Cmp_Tuple(REBVAL *t1, REBVAL *t2)
/*
**	Given two tuples, compare them.
**
***********************************************************************/
{
	REBCNT	len;
	REBYTE	*vp1, *vp2;
	REBINT	n;

	len = MAX(VAL_TUPLE_LEN(t1), VAL_TUPLE_LEN(t2));
	vp1 = VAL_TUPLE(t1);
	vp2 = VAL_TUPLE(t2);

	for (;len > 0; len--, vp1++,vp2++) {
		n = (REBINT)(*vp1 - *vp2);
		if (n != 0)
			return n;
	}
	return 0;
}
コード例 #8
0
ファイル: t-tuple.c プロジェクト: hostilefork/rebol
//
//  PD_Tuple: C
//
// Implements PATH and SET_PATH for tuple.
// Sets DS_TOP if found. Always returns 0.
//
REBINT PD_Tuple(REBPVS *pvs)
{
    const REBVAL *setval;
    REBINT n;
    REBINT i;
    REBYTE *dat;
    REBINT len;

    dat = VAL_TUPLE(pvs->value);
    len = VAL_TUPLE_LEN(pvs->value);

    if (len < 3) {
        len = 3;
    }

    n = Get_Num_From_Arg(pvs->selector);

    if ((setval = pvs->opt_setval)) {
        if (n <= 0 || n > cast(REBINT, MAX_TUPLE))
            fail (Error_Bad_Path_Select(pvs));

        if (IS_INTEGER(setval) || IS_DECIMAL(setval))
            i = Int32(setval);
        else if (IS_BLANK(setval)) {
            n--;
            CLEAR(dat + n, MAX_TUPLE - n);
            VAL_TUPLE_LEN(pvs->value) = n;
            return PE_OK;
        }
        else
            fail (Error_Bad_Path_Set(pvs));

        if (i < 0) i = 0;
        else if (i > 255) i = 255;

        dat[n - 1] = i;
        if (n > len)
            VAL_TUPLE_LEN(pvs->value) = n;

        return PE_OK;
    }
    else {
        if (n > 0 && n <= len) {
            SET_INTEGER(pvs->store, dat[n - 1]);
            return PE_USE_STORE;
        }
        else return PE_NONE;
    }
}
コード例 #9
0
ファイル: t-tuple.c プロジェクト: 51weekend/r3
*/	REBINT PD_Tuple(REBPVS *pvs)
/*
**		Implements PATH and SET_PATH for tuple.
**		Sets DS_TOP if found. Always returns 0.
**
***********************************************************************/
{
	REBVAL *val;
	REBINT n;
	REBINT i;
	REBYTE *dat;
	REBINT len;

	dat = VAL_TUPLE(pvs->value);
	len = VAL_TUPLE_LEN(pvs->value);
	if (len < 3) len = 3;
	n = Get_Num_Arg(pvs->select);

	if (NZ(val = pvs->setval)) {
		if (n <= 0 || n > MAX_TUPLE) return PE_BAD_SELECT;
		if (IS_INTEGER(val) || IS_DECIMAL(val)) i = Int32(val);
		else if (IS_NONE(val)) {
			n--;
			CLEAR(dat+n, MAX_TUPLE-n);
			VAL_TUPLE_LEN(pvs->value) = n;
			return PE_OK;
		}
		else return PE_BAD_SET;
		if (i < 0) i = 0;
		else if (i > 255) i = 255;
		dat[n-1] = i;
		if (n > len) VAL_TUPLE_LEN(pvs->value) = n;
		return PE_OK;
	} else {
		if (n > 0 && n <= len) {
			SET_INTEGER(pvs->store, dat[n-1]);
			return PE_USE;
		}
		else return PE_NONE;
	}
}
コード例 #10
0
ファイル: t-tuple.c プロジェクト: hostilefork/rebol
//
//  Poke_Tuple_Immediate: C
//
// !!! Note: In the current implementation, tuples are immediate values.
// So a POKE only changes the `value` in your hand.
//
void Poke_Tuple_Immediate(
    REBVAL *value,
    const REBVAL *picker,
    const REBVAL *poke
) {
    REBYTE *dat = VAL_TUPLE(value);

    REBINT len = VAL_TUPLE_LEN(value);
    if (len < 3)
        len = 3;

    REBINT n = Get_Num_From_Arg(picker);
    if (n <= 0 || n > cast(REBINT, MAX_TUPLE))
        fail (Error_Out_Of_Range(picker));

    REBINT i;
    if (IS_INTEGER(poke) || IS_DECIMAL(poke))
        i = Int32(poke);
    else if (IS_BLANK(poke)) {
        n--;
        CLEAR(dat + n, MAX_TUPLE - n);
        VAL_TUPLE_LEN(value) = n;
        return;
    }
    else
        fail (poke);

    if (i < 0)
        i = 0;
    else if (i > 255)
        i = 255;

    dat[n - 1] = i;
    if (n > len)
        VAL_TUPLE_LEN(value) = n;
}
コード例 #11
0
ファイル: t-tuple.c プロジェクト: hostilefork/rebol
//
//  Pick_Tuple: C
//
void Pick_Tuple(REBVAL *out, const REBVAL *value, const REBVAL *picker)
{
    const REBYTE *dat = VAL_TUPLE(value);

    REBINT len = VAL_TUPLE_LEN(value);
    if (len < 3)
        len = 3;

    REBINT n = Get_Num_From_Arg(picker);

    // This uses modulus to avoid having a conditional access into the array,
    // which would trigger Spectre mitigation:
    //
    // https://stackoverflow.com/questions/50399940/
    //
    // By always accessing the array and always being in bounds, there's no
    // speculative execution accessing unbound locations.
    //
    REBYTE byte = dat[(n - 1) % len];
    if (n > 0 and n <= len)
        Init_Integer(out, byte);
    else
        Init_Nulled(out);
}
コード例 #12
0
ファイル: t-gob.c プロジェクト: xqlab/r3
*/	static REBFLG Set_GOB_Var(REBGOB *gob, REBVAL *word, REBVAL *val)
/*
***********************************************************************/
{
    switch (VAL_WORD_CANON(word)) {
    case SYM_OFFSET:
        return Set_Pair(&(gob->offset), val);

    case SYM_SIZE:
        return Set_Pair(&gob->size, val);

    case SYM_IMAGE:
        CLR_GOB_OPAQUE(gob);
        if (IS_IMAGE(val)) {
            SET_GOB_TYPE(gob, GOBT_IMAGE);
            GOB_W(gob) = (REBD32)VAL_IMAGE_WIDE(val);
            GOB_H(gob) = (REBD32)VAL_IMAGE_HIGH(val);
            GOB_CONTENT(gob) = VAL_SERIES(val);
//			if (!VAL_IMAGE_TRANSP(val)) SET_GOB_OPAQUE(gob);
        }
        else if (IS_NONE(val)) SET_GOB_TYPE(gob, GOBT_NONE);
        else return FALSE;
        break;

    case SYM_DRAW:
        CLR_GOB_OPAQUE(gob);
        if (IS_BLOCK(val)) {
            SET_GOB_TYPE(gob, GOBT_DRAW);
            GOB_CONTENT(gob) = VAL_SERIES(val);
        }
        else if (IS_NONE(val)) SET_GOB_TYPE(gob, GOBT_NONE);
        else return FALSE;
        break;

    case SYM_TEXT:
        CLR_GOB_OPAQUE(gob);
        if (IS_BLOCK(val)) {
            SET_GOB_TYPE(gob, GOBT_TEXT);
            GOB_CONTENT(gob) = VAL_SERIES(val);
        }
        else if (IS_STRING(val)) {
            SET_GOB_TYPE(gob, GOBT_STRING);
            GOB_CONTENT(gob) = VAL_SERIES(val);
        }
        else if (IS_NONE(val)) SET_GOB_TYPE(gob, GOBT_NONE);
        else return FALSE;
        break;

    case SYM_EFFECT:
        CLR_GOB_OPAQUE(gob);
        if (IS_BLOCK(val)) {
            SET_GOB_TYPE(gob, GOBT_EFFECT);
            GOB_CONTENT(gob) = VAL_SERIES(val);
        }
        else if (IS_NONE(val)) SET_GOB_TYPE(gob, GOBT_NONE);
        else return FALSE;
        break;

    case SYM_COLOR:
        CLR_GOB_OPAQUE(gob);
        if (IS_TUPLE(val)) {
            SET_GOB_TYPE(gob, GOBT_COLOR);
            Set_Pixel_Tuple((REBYTE*)&GOB_CONTENT(gob), val);
            if (VAL_TUPLE_LEN(val) < 4 || VAL_TUPLE(val)[3] == 0)
                SET_GOB_OPAQUE(gob);
        }
        else if (IS_NONE(val)) SET_GOB_TYPE(gob, GOBT_NONE);
        break;

    case SYM_PANE:
        if (GOB_PANE(gob)) Clear_Series(GOB_PANE(gob));
        if (IS_BLOCK(val))
            Insert_Gobs(gob, VAL_BLK_DATA(val), 0, VAL_BLK_LEN(val), 0);
        else if (IS_GOB(val))
            Insert_Gobs(gob, val, 0, 1, 0);
        else if (IS_NONE(val))
            gob->pane = 0;
        else
            return FALSE;
        break;

    case SYM_ALPHA:
        GOB_ALPHA(gob) = Clip_Int(Int32(val), 0, 255);
        break;

    case SYM_DATA:
        SET_GOB_DTYPE(gob, GOBD_NONE);
        if (IS_OBJECT(val)) {
            SET_GOB_DTYPE(gob, GOBD_OBJECT);
            SET_GOB_DATA(gob, VAL_OBJ_FRAME(val));
        }
        else if (IS_BLOCK(val)) {
            SET_GOB_DTYPE(gob, GOBD_BLOCK);
            SET_GOB_DATA(gob, VAL_SERIES(val));
        }
        else if (IS_STRING(val)) {
            SET_GOB_DTYPE(gob, GOBD_STRING);
            SET_GOB_DATA(gob, VAL_SERIES(val));
        }
        else if (IS_BINARY(val)) {
            SET_GOB_DTYPE(gob, GOBD_BINARY);
            SET_GOB_DATA(gob, VAL_SERIES(val));
        }
        else if (IS_INTEGER(val)) {
            SET_GOB_DTYPE(gob, GOBD_INTEGER);
            SET_GOB_DATA(gob, (void*)(REBIPT)VAL_INT64(val));
        }
        else if (IS_NONE(val))
            SET_GOB_TYPE(gob, GOBT_NONE);
        else return FALSE;
        break;

    case SYM_FLAGS:
        if (IS_WORD(val)) Set_Gob_Flag(gob, val);
        else if (IS_BLOCK(val)) {
            gob->flags = 0;
            for (val = VAL_BLK(val); NOT_END(val); val++) {
                if (IS_WORD(val)) Set_Gob_Flag(gob, val);
            }
        }
        break;

    case SYM_OWNER:
        if (IS_GOB(val))
            GOB_TMP_OWNER(gob) = VAL_GOB(val);
        else
            return FALSE;
        break;

    default:
        return FALSE;
    }
    return TRUE;
}
コード例 #13
0
ファイル: t-tuple.c プロジェクト: hostilefork/rebol
//
//  MAKE_Tuple: C
//
REB_R MAKE_Tuple(
    REBVAL *out,
    enum Reb_Kind kind,
    const REBVAL *opt_parent,
    const REBVAL *arg
){
    assert(kind == REB_TUPLE);
    if (opt_parent)
        fail (Error_Bad_Make_Parent(kind, opt_parent));

    if (IS_TUPLE(arg))
        return Move_Value(out, arg);

    RESET_CELL(out, REB_TUPLE, CELL_MASK_NONE);
    REBYTE *vp = VAL_TUPLE(out);

    // !!! Net lookup parses IP addresses out of `tcp://93.184.216.34` or
    // similar URL!s.  In Rebol3 these captures come back the same type
    // as the input instead of as STRING!, which was a latent bug in the
    // network code of the 12-Dec-2012 release:
    //
    // https://github.com/rebol/rebol/blob/master/src/mezz/sys-ports.r#L110
    //
    // All attempts to convert a URL!-flavored IP address failed.  Taking
    // URL! here fixes it, though there are still open questions.
    //
    if (IS_TEXT(arg) or IS_URL(arg)) {
        REBSIZ size;
        const REBYTE *bp
            = Analyze_String_For_Scan(&size, arg, MAX_SCAN_TUPLE);

        if (Scan_Tuple(out, bp, size) == nullptr)
            fail (arg);
        return out;
    }

    if (ANY_ARRAY(arg)) {
        REBCNT len = 0;
        REBINT n;

        RELVAL *item = VAL_ARRAY_AT(arg);

        for (; NOT_END(item); ++item, ++vp, ++len) {
            if (len >= MAX_TUPLE)
                goto bad_make;
            if (IS_INTEGER(item)) {
                n = Int32(item);
            }
            else if (IS_CHAR(item)) {
                n = VAL_CHAR(item);
            }
            else
                goto bad_make;

            if (n > 255 || n < 0)
                goto bad_make;
            *vp = n;
        }

        VAL_TUPLE_LEN(out) = len;

        for (; len < MAX_TUPLE; len++) *vp++ = 0;
        return out;
    }

    REBCNT alen;

    if (IS_ISSUE(arg)) {
        REBSTR *spelling = VAL_STRING(arg);
        const REBYTE *ap = STR_HEAD(spelling);
        size_t size = STR_SIZE(spelling); // UTF-8 len
        if (size & 1)
            fail (arg); // must have even # of chars
        size /= 2;
        if (size > MAX_TUPLE)
            fail (arg); // valid even for UTF-8
        VAL_TUPLE_LEN(out) = size;
        for (alen = 0; alen < size; alen++) {
            REBYTE decoded;
            if ((ap = Scan_Hex2(&decoded, ap)) == NULL)
                fail (arg);
            *vp++ = decoded;
        }
    }
    else if (IS_BINARY(arg)) {
        REBYTE *ap = VAL_BIN_AT(arg);
        REBCNT len = VAL_LEN_AT(arg);
        if (len > MAX_TUPLE) len = MAX_TUPLE;
        VAL_TUPLE_LEN(out) = len;
        for (alen = 0; alen < len; alen++) *vp++ = *ap++;
    }
    else
        fail (arg);

    for (; alen < MAX_TUPLE; alen++) *vp++ = 0;
    return out;

  bad_make:
    fail (Error_Bad_Make(REB_TUPLE, arg));
}
コード例 #14
0
ファイル: t-tuple.c プロジェクト: hostilefork/rebol
//
//  MAKE_Tuple: C
//
void MAKE_Tuple(REBVAL *out, enum Reb_Kind type, const REBVAL *arg)
{
    if (IS_TUPLE(arg)) {
        *out = *arg;
        return;
    }

    VAL_RESET_HEADER(out, REB_TUPLE);
    REBYTE *vp = VAL_TUPLE(out);

    // !!! Net lookup parses IP addresses out of `tcp://93.184.216.34` or
    // similar URL!s.  In Rebol3 these captures come back the same type
    // as the input instead of as STRING!, which was a latent bug in the
    // network code of the 12-Dec-2012 release:
    //
    // https://github.com/rebol/rebol/blob/master/src/mezz/sys-ports.r#L110
    //
    // All attempts to convert a URL!-flavored IP address failed.  Taking
    // URL! here fixes it, though there are still open questions.
    //
    if (IS_STRING(arg) || IS_URL(arg)) {
        REBCNT len;
        REBYTE *ap = Temp_Byte_Chars_May_Fail(arg, MAX_SCAN_TUPLE, &len, FALSE);
        if (Scan_Tuple(ap, len, out))
            return;
        goto bad_arg;
    }

    if (ANY_ARRAY(arg)) {
        REBCNT len = 0;
        REBINT n;

        RELVAL *item = VAL_ARRAY_AT(arg);

        for (; NOT_END(item); ++item, ++vp, ++len) {
            if (len >= MAX_TUPLE) goto bad_make;
            if (IS_INTEGER(item)) {
                n = Int32(item);
            }
            else if (IS_CHAR(item)) {
                n = VAL_CHAR(item);
            }
            else
                goto bad_make;

            if (n > 255 || n < 0) goto bad_make;
            *vp = n;
        }

        VAL_TUPLE_LEN(out) = len;

        for (; len < MAX_TUPLE; len++) *vp++ = 0;
        return;
    }

    REBCNT alen;

    if (IS_ISSUE(arg)) {
        REBUNI c;
        const REBYTE *ap = VAL_WORD_HEAD(arg);
        REBCNT len = LEN_BYTES(ap);  // UTF-8 len
        if (len & 1) goto bad_arg; // must have even # of chars
        len /= 2;
        if (len > MAX_TUPLE) goto bad_arg; // valid even for UTF-8
        VAL_TUPLE_LEN(out) = len;
        for (alen = 0; alen < len; alen++) {
            const REBOOL unicode = FALSE;
            if (!Scan_Hex2(ap, &c, unicode)) goto bad_arg;
            *vp++ = cast(REBYTE, c);
            ap += 2;
        }
    }
    else if (IS_BINARY(arg)) {
        REBYTE *ap = VAL_BIN_AT(arg);
        REBCNT len = VAL_LEN_AT(arg);
        if (len > MAX_TUPLE) len = MAX_TUPLE;
        VAL_TUPLE_LEN(out) = len;
        for (alen = 0; alen < len; alen++) *vp++ = *ap++;
    }
    else goto bad_arg;

    for (; alen < MAX_TUPLE; alen++) *vp++ = 0;
    return;

bad_arg:
    fail (Error_Invalid_Arg(arg));

bad_make:
    fail (Error_Bad_Make(REB_TUPLE, arg));
}
コード例 #15
0
ファイル: c-error.c プロジェクト: 51weekend/r3
*/	REBYTE *Security_Policy(REBCNT sym, REBVAL *name)
/*
**	Given a security symbol (like FILE) and a value (like the file
**	path) returns the security policy (RWX) allowed for it.
**
**	Args:
**
**		sym:  word that represents the type ['file 'net]
**		name: file or path value
**
**	Returns BTYE array of flags for the policy class:
**
**		flags: [rrrr wwww xxxx ----]
**
**		Where each byte is:
**			0: SEC_ALLOW
**			1: SEC_ASK
**			2: SEC_THROW
**			3: SEC_QUIT
**
**	The secuity is defined by the system/state/policies object, that
**	is of the form:
**
**		[
**			file:  [%file1 tuple-flags %file2 ... default tuple-flags]
**			net:   [...]
**			call:  tuple-flags
**			stack: tuple-flags
**			eval:  integer (limit)
**		]
**
***********************************************************************/
{
	REBVAL *policy = Get_System(SYS_STATE, STATE_POLICIES);
	REBYTE *flags;
	REBCNT len;
	REBCNT errcode = RE_SECURITY_ERROR;

	if (!IS_OBJECT(policy)) goto error;

	// Find the security class in the block: (file net call...)
	policy = Find_Word_Value(VAL_OBJ_FRAME(policy), sym);
	if (!policy) goto error;

	// Obtain the policies for it:
	// Check for a master tuple: [file rrrr.wwww.xxxx]
	if (IS_TUPLE(policy)) return VAL_TUPLE(policy); // non-aligned
	// removed A90: if (IS_INTEGER(policy)) return (REBYTE*)VAL_INT64(policy); // probably not used

	// Only other form is detailed block:
	if (!IS_BLOCK(policy)) goto error;

	// Scan block of policies for the class: [file [allow read quit write]]
	len = 0;	// file or url length
	flags = 0;	// policy flags
	for (policy = VAL_BLK(policy); NOT_END(policy); policy += 2) {

		// Must be a policy tuple:
		if (!IS_TUPLE(policy+1)) goto error;

		// Is it a policy word:
		if (IS_WORD(policy)) { // any word works here
			// If no strings found, use the default:
			if (len == 0) flags = VAL_TUPLE(policy+1); // non-aligned
		}

		// Is it a string (file or URL):
		else if (ANY_BINSTR(policy) && name) {
			//Debug_Fmt("sec: %r %r", policy, name);
			if (Match_Sub_Path(VAL_SERIES(policy), VAL_SERIES(name))) {
				// Is the match adequate?
				if (VAL_TAIL(name) >= len) {
					len = VAL_TAIL(name);
					flags = VAL_TUPLE(policy+1); // non-aligned
				}
			}
		}
		else goto error;
	}

	if (!flags) {
		errcode = RE_SECURITY;
		policy = name ? name : 0;
error:
		if (!policy) {
			Init_Word(DS_TOP, sym);
			policy = DS_TOP;
		}
		Trap1(errcode, policy);
	}

	return flags;
}
コード例 #16
0
ファイル: p-net.c プロジェクト: fort-ascension/ren-c
//
//  Transport_Actor: C
//
static REB_R Transport_Actor(struct Reb_Call *call_, REBSER *port, REBCNT action, enum Transport_Types proto)
{
    REBREQ *sock;   // IO request
    REBVAL *spec;   // port spec
    REBVAL *arg;    // action argument value
    REBVAL *val;    // e.g. port number value
    REBINT result;  // IO result
    REBCNT refs;    // refinement argument flags
    REBCNT len;     // generic length
    REBSER *ser;    // simplifier

    Validate_Port(port, action);

    *D_OUT = *D_ARG(1);
    arg = DS_ARGC > 1 ? D_ARG(2) : NULL;

    sock = cast(REBREQ*, Use_Port_State(port, RDI_NET, sizeof(*sock)));
    if (proto == TRANSPORT_UDP) {
        SET_FLAG(sock->modes, RST_UDP);
    }
    //Debug_Fmt("Sock: %x", sock);
    spec = OFV(port, STD_PORT_SPEC);
    if (!IS_OBJECT(spec)) fail (Error(RE_INVALID_PORT));

    // sock->timeout = 4000; // where does this go? !!!

    // HOW TO PREVENT OVERWRITE DURING BUSY OPERATION!!!
    // Should it just ignore it or cause an error?

    // Actions for an unopened socket:
    if (!IS_OPEN(sock)) {

        switch (action) {   // Ordered by frequency

        case A_OPEN:

            arg = Obj_Value(spec, STD_PORT_SPEC_NET_HOST);
            val = Obj_Value(spec, STD_PORT_SPEC_NET_PORT_ID);

            if (OS_DO_DEVICE(sock, RDC_OPEN))
                fail (Error_On_Port(RE_CANNOT_OPEN, port, -12));
            SET_OPEN(sock);

            // Lookup host name (an extra TCP device step):
            if (IS_STRING(arg)) {
                sock->common.data = VAL_BIN(arg);
                sock->special.net.remote_port = IS_INTEGER(val) ? VAL_INT32(val) : 80;
                result = OS_DO_DEVICE(sock, RDC_LOOKUP);  // sets remote_ip field
                if (result < 0)
                    fail (Error_On_Port(RE_NO_CONNECT, port, sock->error));
                return R_OUT;
            }

            // Host IP specified:
            else if (IS_TUPLE(arg)) {
                sock->special.net.remote_port = IS_INTEGER(val) ? VAL_INT32(val) : 80;
                memcpy(&sock->special.net.remote_ip, VAL_TUPLE(arg), 4);
                break;
            }

            // No host, must be a LISTEN socket:
            else if (IS_NONE(arg)) {
                SET_FLAG(sock->modes, RST_LISTEN);
                sock->common.data = 0; // where ACCEPT requests are queued
                sock->special.net.local_port = IS_INTEGER(val) ? VAL_INT32(val) : 8000;
                break;
            }
            else
                fail (Error_On_Port(RE_INVALID_SPEC, port, -10));

        case A_CLOSE:
            return R_OUT;

        case A_OPENQ:
            return R_FALSE;

        case A_UPDATE:  // allowed after a close
            break;

        default:
            fail (Error_On_Port(RE_NOT_OPEN, port, -12));
        }
    }

    // Actions for an open socket:
    switch (action) {   // Ordered by frequency

    case A_UPDATE:
        // Update the port object after a READ or WRITE operation.
        // This is normally called by the WAKE-UP function.
        arg = OFV(port, STD_PORT_DATA);
        if (sock->command == RDC_READ) {
            if (ANY_BINSTR(arg)) VAL_TAIL(arg) += sock->actual;
        }
        else if (sock->command == RDC_WRITE) {
            SET_NONE(arg);  // Write is done.
        }
        return R_NONE;

    case A_READ:
        // Read data into a buffer, expanding the buffer if needed.
        // If no length is given, program must stop it at some point.
        refs = Find_Refines(call_, ALL_READ_REFS);
        if (
            !GET_FLAG(sock->modes, RST_UDP)
            && !GET_FLAG(sock->state, RSM_CONNECT)
        ) {
            fail (Error_On_Port(RE_NOT_CONNECTED, port, -15));
        }

        // Setup the read buffer (allocate a buffer if needed):
        arg = OFV(port, STD_PORT_DATA);
        if (!IS_STRING(arg) && !IS_BINARY(arg)) {
            Val_Init_Binary(arg, Make_Binary(NET_BUF_SIZE));
        }
        ser = VAL_SERIES(arg);
        sock->length = SERIES_AVAIL(ser); // space available
        if (sock->length < NET_BUF_SIZE/2) Extend_Series(ser, NET_BUF_SIZE);
        sock->length = SERIES_AVAIL(ser);
        sock->common.data = STR_TAIL(ser); // write at tail
        //if (SERIES_TAIL(ser) == 0)
        sock->actual = 0;  // Actual for THIS read, not for total.

        //Print("(max read length %d)", sock->length);
        result = OS_DO_DEVICE(sock, RDC_READ); // recv can happen immediately
        if (result < 0) fail (Error_On_Port(RE_READ_ERROR, port, sock->error));
        break;

    case A_WRITE:
        // Write the entire argument string to the network.
        // The lower level write code continues until done.

        refs = Find_Refines(call_, ALL_WRITE_REFS);
        if (!GET_FLAG(sock->modes, RST_UDP)
            && !GET_FLAG(sock->state, RSM_CONNECT))
            fail (Error_On_Port(RE_NOT_CONNECTED, port, -15));

        // Determine length. Clip /PART to size of string if needed.
        spec = D_ARG(2);
        len = VAL_LEN(spec);
        if (refs & AM_WRITE_PART) {
            REBCNT n = Int32s(D_ARG(ARG_WRITE_LIMIT), 0);
            if (n <= len) len = n;
        }

        // Setup the write:
        *OFV(port, STD_PORT_DATA) = *spec;  // keep it GC safe
        sock->length = len;
        sock->common.data = VAL_BIN_DATA(spec);
        sock->actual = 0;

        //Print("(write length %d)", len);
        result = OS_DO_DEVICE(sock, RDC_WRITE); // send can happen immediately
        if (result < 0) fail (Error_On_Port(RE_WRITE_ERROR, port, sock->error));
        if (result == DR_DONE) SET_NONE(OFV(port, STD_PORT_DATA));
        break;

    case A_PICK:
        // FIRST server-port returns new port connection.
        len = Get_Num_Arg(arg); // Position
        if (len == 1 && GET_FLAG(sock->modes, RST_LISTEN) && sock->common.data)
            Accept_New_Port(D_OUT, port, sock); // sets D_OUT
        else
            fail (Error_Out_Of_Range(arg));
        break;

    case A_QUERY:
        // Get specific information - the scheme's info object.
        // Special notation allows just getting part of the info.
        Ret_Query_Net(port, sock, D_OUT);
        break;

    case A_OPENQ:
        // Connect for clients, bind for servers:
        if (sock->state & ((1<<RSM_CONNECT) | (1<<RSM_BIND))) return R_TRUE;
        return R_FALSE;

    case A_CLOSE:
        if (IS_OPEN(sock)) {
            OS_DO_DEVICE(sock, RDC_CLOSE);
            SET_CLOSED(sock);
        }
        break;

    case A_LENGTH:
        arg = OFV(port, STD_PORT_DATA);
        len = ANY_SERIES(arg) ? VAL_TAIL(arg) : 0;
        SET_INTEGER(D_OUT, len);
        break;

    case A_OPEN:
        result = OS_DO_DEVICE(sock, RDC_CONNECT);
        if (result < 0)
            fail (Error_On_Port(RE_NO_CONNECT, port, sock->error));
        break;

    case A_DELETE: // Temporary to TEST error handler!
        {
            REBVAL *event = Append_Event();     // sets signal
            VAL_SET(event, REB_EVENT);      // (has more space, if we need it)
            VAL_EVENT_TYPE(event) = EVT_ERROR;
            VAL_EVENT_DATA(event) = 101;
            VAL_EVENT_REQ(event) = sock;
        }
        break;

    default:
        fail (Error_Illegal_Action(REB_PORT, action));
    }

    return R_OUT;
}
コード例 #17
0
ファイル: host-text.c プロジェクト: RamchandraApte/rebol
*/	REBINT Text_Gob(void *richtext, REBSER *block)
/*
**		Handles all commands for the TEXT dialect as specified
**		in the system/dialects/text object.
**
**		This function calls the REBOL_Dialect interpreter to
**		parse the dialect and build and return the command number
**		(the index offset in the text object above) and a block
**		of arguments. (For now, just a REBOL block, but this could
**		be changed to isolate it from changes in REBOL's internals).
**
**		Each arg will be of the specified datatype (given in the
**		dialect) or NONE when no argument of that type was given
**		and this code must determine the proper default value.
**
**		If the cmd result is zero, then it is either the end of
**		the block, or an error has occurred. If the error value
**		is non-zero, then it was an error.
**
***********************************************************************/
{
	REBCNT index = 0;
	REBINT cmd;
	REBSER *args = 0;
	REBVAL *arg;
	REBCNT nargs;

	//font object conversion related values
	REBFNT* font;
	REBVAL* val;
	REBPAR  offset;
	REBPAR  space;

	//para object conversion related values
	REBPRA* para;
	REBPAR  origin;
	REBPAR  margin;
	REBPAR  indent;
	REBPAR  scroll;

	do {
		cmd = Reb_Dialect(DIALECTS_TEXT, block, &index, &args);

		if (cmd == 0) return 0;
		if (cmd < 0) {
//			Reb_Print("ERROR: %d, Index %d", -cmd, index);
			return -((REBINT)index+1);
		}
//		else
//			Reb_Print("TEXT: Cmd %d, Index %d, Args %m", cmd, index, args);

		arg = BLK_HEAD(args);
		nargs = SERIES_TAIL(args);
//		Reb_Print("Number of args: %d", nargs);

		switch (cmd) {

		case TW_TYPE_SPEC:

			if (IS_STRING(arg)) {
				rt_text(richtext, ARG_STRING(0), index);
			} else if (IS_TUPLE(arg)) {
				rt_color(richtext, ARG_TUPLE(0));
			}
			break;
		case TW_ANTI_ALIAS:
			rt_anti_alias(richtext, ARG_OPT_LOGIC(0));
			break;

		case TW_SCROLL:
			rt_scroll(richtext, ARG_PAIR(0));
			break;

		case TW_BOLD:
		case TW_B:
			rt_bold(richtext, ARG_OPT_LOGIC(0));
			break;

		case TW_ITALIC:
		case TW_I:
			rt_italic(richtext, ARG_OPT_LOGIC(0));
			break;

		case TW_UNDERLINE:
		case TW_U:
			rt_underline(richtext, ARG_OPT_LOGIC(0));
			break;
		case TW_CENTER:
			rt_center(richtext);
			break;
		case TW_LEFT:
			rt_left(richtext);
			break;
		case TW_RIGHT:
			rt_right(richtext);
			break;
		case TW_FONT:

		if (!IS_OBJECT(arg)) break;

		font = (REBFNT*)rt_get_font(richtext);

		val = BLK_HEAD(ARG_OBJECT(0))+1;

		if (IS_STRING(val)) {
			font->name = VAL_STRING(val);
		}

//		Reb_Print("font/name: %s", font->name);

		val++;

		if (IS_BLOCK(val)) {
			REBSER* styles = VAL_SERIES(val);
			REBVAL* slot = BLK_HEAD(styles);
			REBCNT len = SERIES_TAIL(styles) ,i;

			for (i = 0;i<len;i++){
				if (IS_WORD(slot+i)){
					set_font_styles(font, slot+i);
				}
			}

		} else if (IS_WORD(val)) {
			set_font_styles(font, val);
		}

		val++;
		if (IS_INTEGER(val)) {
			font->size = VAL_INT32(val);
		}

//		Reb_Print("font/size: %d", font->size);

		val++;
		if ((IS_TUPLE(val)) || (IS_NONE(val))) {
			COPY_MEM(font->color,VAL_TUPLE(val), 4);
		}

//		Reb_Print("font/color: %d.%d.%d.%d", font->color[0],font->color[1],font->color[2],font->color[3]);

		val++;
		if ((IS_PAIR(val)) || (IS_NONE(val))) {
			offset = VAL_PAIR(val);
			font->offset_x = offset.x;
			font->offset_y = offset.y;
		}

//		Reb_Print("font/offset: %dx%d", offset.x,offset.y);

		val++;
		if ((IS_PAIR(val)) || (IS_NONE(val))) {
			space = VAL_PAIR(val);
			font->space_x = space.x;
			font->space_y = space.y;
		}

//		Reb_Print("font/space: %dx%d", space.x, space.y);


		val++;

		font->shadow_x = 0;
		font->shadow_y = 0;

		if (IS_BLOCK(val)) {
			REBSER* ser = VAL_SERIES(val);
			REBVAL* slot = BLK_HEAD(ser);
			REBCNT len = SERIES_TAIL(ser) ,i;

			for (i = 0;i<len;i++){
				if (IS_PAIR(slot)) {
					REBPAR shadow = VAL_PAIR(slot);
					font->shadow_x = shadow.x;
					font->shadow_y = shadow.y;
				} else if (IS_TUPLE(slot)) {
					COPY_MEM(font->shadow_color,VAL_TUPLE(slot), 4);
				} else if (IS_INTEGER(slot)) {
					font->shadow_blur = VAL_INT32(slot);
				}
				slot++;
			}
		} else if (IS_PAIR(val)) {
			REBPAR shadow = VAL_PAIR(val);
			font->shadow_x = shadow.x;
			font->shadow_y = shadow.y;
		}

			rt_font(richtext, font);
			break;

		case TW_PARA:
			if (!IS_OBJECT(arg)) break;

			para = (REBPRA*)rt_get_para(richtext);

			val = BLK_HEAD(ARG_OBJECT(0))+1;


			if (IS_PAIR(val)) {
				origin = VAL_PAIR(val);
				para->origin_x = origin.x;
				para->origin_y = origin.y;
			}

//			Reb_Print("para/origin: %dx%d", origin.x, origin.y);

			val++;
			if (IS_PAIR(val)) {
				margin = VAL_PAIR(val);
				para->margin_x = margin.x;
				para->margin_y = margin.y;
			}

//			Reb_Print("para/margin: %dx%d", margin.x, margin.y);

			val++;
			if (IS_PAIR(val)) {
				indent = VAL_PAIR(val);
				para->indent_x = indent.x;
				para->indent_y = indent.y;
			}

//			Reb_Print("para/indent: %dx%d", indent.x, indent.y);

			val++;
			if (IS_INTEGER(val)) {
				para->tabs = VAL_INT32(val);
			}

//			Reb_Print("para/tabs: %d", para->tabs);

			val++;
			if (IS_LOGIC(val)) {
				para->wrap = VAL_LOGIC(val);
			}

//			Reb_Print("para/wrap?: %d", para->wrap);

			val++;
			if (IS_PAIR(val)) {
				scroll = VAL_PAIR(val);
				para->scroll_x = scroll.x;
				para->scroll_y = scroll.y;
			}
//			Reb_Print("para/scroll: %dx%d", scroll.x, scroll.y);

			val++;

			if (IS_WORD(val)) {
				REBINT result = Reb_Find_Word(VAL_WORD_SYM(val), Symbol_Ids, 0);
				switch (result){
					case SW_RIGHT:
					case SW_LEFT:
					case SW_CENTER:
						para->align = result;
						break;
					default:
						para->align = SW_LEFT;
						break;
				}

			}

			val++;

			if (IS_WORD(val)) {
				REBINT result = Reb_Find_Word(VAL_WORD_SYM(val), Symbol_Ids, 0);
				switch (result){
					case SW_TOP:
					case SW_BOTTOM:
					case SW_MIDDLE:
						para->valign = result;
						break;
					default:
						para->valign = SW_TOP;
						break;
				}
			}

			rt_para(richtext, para);
			break;

		case TW_SIZE:
			rt_font_size(richtext, ARG_INTEGER(0));
			break;

		case TW_SHADOW:
			rt_shadow(richtext, &ARG_PAIR(0), ARG_TUPLE(1), ARG_INTEGER(2));
			break;

		case TW_DROP:
			rt_drop(richtext, ARG_OPT_INTEGER(0));
			break;

		case TW_NEWLINE:
		case TW_NL:
			rt_newline(richtext, index);
			break;
		case TW_CARET:
			{
				REBPAR caret = {0,0};
				REBPAR highlightStart = {0,0};
				REBPAR highlightEnd = {0,0};
				REBVAL *slot;
				if (!IS_OBJECT(arg)) break;

				val = BLK_HEAD(ARG_OBJECT(0))+1;
				if (IS_BLOCK(val)) {
					slot = BLK_HEAD(VAL_SERIES(val));
					if (SERIES_TAIL(VAL_SERIES(val)) == 2 && IS_BLOCK(slot) && IS_STRING(slot+1)){
						caret.x = 1 + slot->data.series.index;
						caret.y = 1 + (slot+1)->data.series.index;;
						//Reb_Print("caret %d, %d", caret.x, caret.y);
					}
				}
				val++;
				if (IS_BLOCK(val)) {
					slot = BLK_HEAD(VAL_SERIES(val));
					if (SERIES_TAIL(VAL_SERIES(val)) == 2 && IS_BLOCK(slot) && IS_STRING(slot+1)){
						highlightStart.x = 1 + slot->data.series.index;
						highlightStart.y = 1 + (slot+1)->data.series.index;;
						//Reb_Print("highlight-start %d, %d", highlightStart.x, highlightStart.y);
					}
				}
				val++;
				if (IS_BLOCK(val)) {
					slot = BLK_HEAD(VAL_SERIES(val));
					if (SERIES_TAIL(VAL_SERIES(val)) == 2 && IS_BLOCK(slot) && IS_STRING(slot+1)){
						highlightEnd.x = 1 + slot->data.series.index;
						highlightEnd.y = 1 + (slot+1)->data.series.index;;
						//Reb_Print("highlight-End %d, %d", highlightEnd.x, highlightEnd.y);
					}
				}

				rt_caret(richtext, &caret, &highlightStart,&highlightEnd);
			}
			break;
		}
	} while (TRUE);
}
コード例 #18
0
ファイル: t-gob.c プロジェクト: Oldes/r3
*/	static REBFLG Set_GOB_Var(REBGOB *gob, REBVAL *word, REBVAL *val)
/*
***********************************************************************/
{
	REBVAL *spec;
	REBVAL *hndl;

	switch (VAL_WORD_CANON(word)) {
	case SYM_OFFSET:
		return Set_Pair(&(gob->offset), val);

	case SYM_SIZE:
		return Set_Pair(&gob->size, val);

	case SYM_IMAGE:
		CLR_GOB_OPAQUE(gob);
		if (IS_IMAGE(val)) {
			SET_GOB_TYPE(gob, GOBT_IMAGE);
			GOB_W(gob) = (REBD32)VAL_IMAGE_WIDE(val);
			GOB_H(gob) = (REBD32)VAL_IMAGE_HIGH(val);
			GOB_CONTENT(gob) = VAL_SERIES(val);
//			if (!VAL_IMAGE_TRANSP(val)) SET_GOB_OPAQUE(gob);
		}
		else if (IS_NONE(val)) SET_GOB_TYPE(gob, GOBT_NONE);
		else return FALSE;
		break;
#ifdef HAS_WIDGET_GOB
	case SYM_WIDGET:
		//printf("WIDGET GOB\n");
		SET_GOB_TYPE(gob, GOBT_WIDGET);
		SET_GOB_OPAQUE(gob);

		GOB_CONTENT(gob) = Make_Block(4);      // [handle type spec data]
		hndl = Append_Value(GOB_CONTENT(gob));
		       Append_Value(GOB_CONTENT(gob)); // used to cache type on host's side
		spec = Append_Value(GOB_CONTENT(gob));
		       Append_Value(GOB_CONTENT(gob)); // used to cache result data

		SET_HANDLE(hndl, 0, SYM_WIDGET, 0);
		
		if (IS_WORD(val) || IS_LIT_WORD(val)) {
			Set_Block(spec, Make_Block(1));
			Append_Val(VAL_SERIES(spec), val);
		}
		else if (IS_BLOCK(val)) {
			Set_Block(spec, VAL_SERIES(val));
		}
		else return FALSE;
		break;
#endif // HAS_WIDGET_GOB

	case SYM_DRAW:
		CLR_GOB_OPAQUE(gob);
		if (IS_BLOCK(val)) {
			SET_GOB_TYPE(gob, GOBT_DRAW);
			GOB_CONTENT(gob) = VAL_SERIES(val);
		}
		else if (IS_NONE(val)) SET_GOB_TYPE(gob, GOBT_NONE);
		else return FALSE;
		break;

	case SYM_TEXT:
		CLR_GOB_OPAQUE(gob);
		if (IS_BLOCK(val)) {
			SET_GOB_TYPE(gob, GOBT_TEXT);
			GOB_CONTENT(gob) = VAL_SERIES(val);
		}
		else if (IS_STRING(val)) {
			SET_GOB_TYPE(gob, GOBT_STRING);
			GOB_CONTENT(gob) = VAL_SERIES(val);
		}
		else if (IS_NONE(val)) SET_GOB_TYPE(gob, GOBT_NONE);
		else return FALSE;
		break;

	case SYM_EFFECT:
		CLR_GOB_OPAQUE(gob);
		if (IS_BLOCK(val)) {
			SET_GOB_TYPE(gob, GOBT_EFFECT);
			GOB_CONTENT(gob) = VAL_SERIES(val);
		}
		else if (IS_NONE(val)) SET_GOB_TYPE(gob, GOBT_NONE);
		else return FALSE;
		break;

	case SYM_COLOR:
		CLR_GOB_OPAQUE(gob);
		if (IS_TUPLE(val)) {
			SET_GOB_TYPE(gob, GOBT_COLOR);
			Set_Pixel_Tuple((REBYTE*)&GOB_CONTENT(gob), val);
			if (VAL_TUPLE_LEN(val) < 4 || VAL_TUPLE(val)[3] == 255)
				SET_GOB_OPAQUE(gob);
		}
		else if (IS_NONE(val)) SET_GOB_TYPE(gob, GOBT_NONE);
		break;

	case SYM_PANE:
		if (GOB_PANE(gob)) Clear_Series(GOB_PANE(gob));
		if (IS_BLOCK(val))
			Insert_Gobs(gob, VAL_BLK_DATA(val), 0, VAL_BLK_LEN(val), 0);
		else if (IS_GOB(val))
			Insert_Gobs(gob, val, 0, 1, 0);
		else if (IS_NONE(val))
			gob->pane = 0;
		else
			return FALSE;
		break;

	case SYM_ALPHA:
		GOB_ALPHA(gob) = Clip_Int(Int32(val), 0, 255);
		break;

	case SYM_DATA:
#ifdef HAS_WIDGET_GOB
		if (GOB_TYPE(gob) == GOBT_WIDGET) {
			OS_SET_WIDGET_DATA(gob, val);
		} else {
#endif
		SET_GOB_DTYPE(gob, GOBD_NONE);
		if (IS_OBJECT(val)) {
			SET_GOB_DTYPE(gob, GOBD_OBJECT);
			SET_GOB_DATA(gob, VAL_OBJ_FRAME(val));
		}
		else if (IS_BLOCK(val)) {
			SET_GOB_DTYPE(gob, GOBD_BLOCK);
			SET_GOB_DATA(gob, VAL_SERIES(val));
		}
		else if (IS_STRING(val)) {
			SET_GOB_DTYPE(gob, GOBD_STRING);
			SET_GOB_DATA(gob, VAL_SERIES(val));
		}
		else if (IS_BINARY(val)) {
			SET_GOB_DTYPE(gob, GOBD_BINARY);
			SET_GOB_DATA(gob, VAL_SERIES(val));
		}
		else if (IS_INTEGER(val)) {
			SET_GOB_DTYPE(gob, GOBD_INTEGER);
			SET_GOB_DATA(gob, (void*)(REBIPT)VAL_INT64(val));
		}
		else if (IS_NONE(val))
			SET_GOB_TYPE(gob, GOBT_NONE);
		else return FALSE;
#ifdef HAS_WIDGET_GOB
		}
#endif
		break;

	case SYM_FLAGS:
		if (IS_WORD(val)) Set_Gob_Flag(gob, val);
		else if (IS_BLOCK(val)) {
			gob->flags = 0;
			for (val = VAL_BLK(val); NOT_END(val); val++) {
				if (IS_WORD(val)) Set_Gob_Flag(gob, val);
			}
		}
		break;

	case SYM_OWNER:
		if (IS_GOB(val))
			GOB_TMP_OWNER(gob) = VAL_GOB(val);
		else
			return FALSE;
		break;

	default:
			return FALSE;
	}
	return TRUE;
}
コード例 #19
0
ファイル: t-string.c プロジェクト: RamchandraApte/rebol
static REBSER *make_binary(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_DATA(arg), VAL_LEN(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 = Encode_UTF8_Value(arg, VAL_LEN(arg), 0);
		break;

	case REB_BLOCK:
		ser = Join_Binary(arg);
		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);
		ser->tail = Encode_UTF8_Char(BIN_HEAD(ser), VAL_CHAR(arg));
		break;

	// MAKE/TO BINARY! <bitset!>
	case REB_BITSET:
		ser = Copy_Bytes(VAL_BIN(arg), VAL_TAIL(arg));
		break;

	// MAKE/TO BINARY! <image!>
	case REB_IMAGE:
	  	ser = Make_Image_Binary(arg);
		break;

	case REB_MONEY:
		ser = Make_Binary(12);
		ser->tail = 12;
		deci_to_binary(ser->data, VAL_DECI(arg));
		ser->data[12] = 0;
		break;

	default:
		ser = 0;
	}

	return ser;
}
コード例 #20
0
ファイル: t-string.c プロジェクト: rgchris/ren-c
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;
}