Ejemplo n.º 1
0
*/  void Expand_Frame(REBSER *frame, REBCNT delta, REBCNT copy)
/*
**      Expand a frame. Copy words if flagged.
**
***********************************************************************/
{
	REBSER *words = FRM_WORD_SERIES(frame);

	Extend_Series(frame, delta);
	BLK_TERM(frame);

	// Expand or copy WORDS block:
	if (copy) {
		REBOOL managed = SERIES_GET_FLAG(FRM_WORD_SERIES(frame), SER_MANAGED);
		FRM_WORD_SERIES(frame) = Copy_Array_Extra_Shallow(words, delta);
		if (managed) MANAGE_SERIES(FRM_WORD_SERIES(frame));
	}
	else {
		Extend_Series(words, delta);
		BLK_TERM(words);
	}
}
Ejemplo n.º 2
0
*/	REBCNT Modify_Array(REBCNT action, REBSER *dst_ser, REBCNT dst_idx, const REBVAL *src_val, REBCNT flags, REBINT dst_len, REBINT dups)
/*
**		action: INSERT, APPEND, CHANGE
**
**		dst_ser:	target
**		dst_idx:	position
**		src_val:    source
**		flags:		AN_ONLY, AN_PART
**		dst_len:	length to remove
**		dups:		dup count
**
**		return: new dst_idx
**
***********************************************************************/
{
    REBCNT tail  = SERIES_TAIL(dst_ser);
    REBINT ilen  = 1;	// length to be inserted
    REBINT size;		// total to insert

#if !defined(NDEBUG)
    REBINT index;
#endif

    if (IS_UNSET(src_val) || dups < 0) {
        // If they are effectively asking for "no action" then all we have
        // to do is return the natural index result for the operation.
        // (APPEND will return 0, insert the tail of the insertion...so index)

        return (action == A_APPEND) ? 0 : dst_idx;
    }

    if (action == A_APPEND || dst_idx > tail) dst_idx = tail;

    // Check /PART, compute LEN:
    if (!GET_FLAG(flags, AN_ONLY) && ANY_ARRAY(src_val)) {
        // Adjust length of insertion if changing /PART:
        if (action != A_CHANGE && GET_FLAG(flags, AN_PART))
            ilen = dst_len;
        else
            ilen = VAL_LEN(src_val);

        // Are we modifying ourselves? If so, copy src_val block first:
        if (dst_ser == VAL_SERIES(src_val)) {
            REBSER *series = Copy_Array_At_Shallow(
                                 VAL_SERIES(src_val), VAL_INDEX(src_val)
                             );
            src_val = BLK_HEAD(series);
        }
        else
            src_val = VAL_BLK_DATA(src_val); // skips by VAL_INDEX values
    }

    // Total to insert:
    size = dups * ilen;

    if (action != A_CHANGE) {
        // Always expand dst_ser for INSERT and APPEND actions:
        Expand_Series(dst_ser, dst_idx, size);
    } else {
        if (size > dst_len)
            Expand_Series(dst_ser, dst_idx, size-dst_len);
        else if (size < dst_len && GET_FLAG(flags, AN_PART))
            Remove_Series(dst_ser, dst_idx, dst_len-size);
        else if (size + dst_idx > tail) {
            EXPAND_SERIES_TAIL(dst_ser, size - (tail - dst_idx));
        }
    }

    tail = (action == A_APPEND) ? 0 : size + dst_idx;

#if !defined(NDEBUG)
    for (index = 0; index < ilen; index++) {
        if (SERIES_GET_FLAG(dst_ser, SER_MANAGED))
            ASSERT_VALUE_MANAGED(&src_val[index]);
    }
#endif

    dst_idx *= SERIES_WIDE(dst_ser); // loop invariant
    ilen  *= SERIES_WIDE(dst_ser); // loop invariant
    for (; dups > 0; dups--) {
        memcpy(dst_ser->data + dst_idx, src_val, ilen);
        dst_idx += ilen;
    }
    TERM_ARRAY(dst_ser);

    return tail;
}