Exemple #1
0
*/	static void trim_lines(REBSER *ser, REBCNT index, REBCNT tail)
/*
**		Remove all newlines and extra space.
**
***********************************************************************/
{
	REBINT pad = 1; // used to allow a single space
	REBUNI uc;
	REBCNT out = index;

	for (; index < tail; index++) {
		uc = GET_ANY_CHAR(ser, index);
		if (IS_WHITE(uc)) {
			uc = ' ';
			if (!pad) {
				SET_ANY_CHAR(ser, out, uc);
				out++;
				pad = 2;
			}
		}
		else {
			SET_ANY_CHAR(ser, out, uc);
			out++;
			pad = 0;
		}
	}

	// Remove extra end pad if found:
	if (pad == 2) out--;

	SET_ANY_CHAR(ser, out, 0);	
	SERIES_TAIL(ser) = out;
}
Exemple #2
0
*/	static void trim_auto(REBSER *ser, REBCNT index, REBCNT tail)
/*
**		Skip any blank lines and then determine indent of
**		first line and make the rest align with it.
**
**		BUG!!! If the indentation uses TABS, then it could
**		fill past the source pointer!
**
***********************************************************************/
{
	REBCNT out = index;
	REBCNT line;
	REBCNT len;
	REBCNT indent;
	REBUNI uc = 0;

	// Skip whitespace, remember start of last line:
	for (line = index; index < tail; index++) {
		uc = GET_ANY_CHAR(ser, index);
		if (!IS_WHITE(uc)) break;
		if (uc == LF) line = index+1;
	}

	// Count the indentation used:
	for (indent = 0; line < index; line++) {
		if (GET_ANY_CHAR(ser, line) == ' ') indent++;
		else indent = (indent + TAB_SIZE) & ~3;
	}

	// For each line, pad with necessary indentation:
	while (index < tail) {
		// Skip to next content, track indentation:
		for (len = 0; index < tail; index++) {
			uc = GET_ANY_CHAR(ser, index);
			if (!IS_SPACE(uc) || len >= indent) break;
			if (uc == ' ') len++;
			else len = (len + TAB_SIZE) & ~3;
		}

		// Indent the line:
		for (; len > indent; len--) {
			SET_ANY_CHAR(ser, out, ' ');
			out++;
		}

		// Copy line contents:
		while (index < tail) {
			uc = GET_ANY_CHAR(ser, index);
			SET_ANY_CHAR(ser, out, uc);
			out++;
			index++;
			if (uc == LF) break;
		}
	}

	SET_ANY_CHAR(ser, out, 0);
	SERIES_TAIL(ser) = out;
}
Exemple #3
0
*/	static void replace_with(REBSER *ser, REBCNT index, REBCNT tail, REBVAL *with)
/*
**		Replace whitespace chars that match WITH string.
**
**		Resulting string is always smaller than it was to start.
**
***********************************************************************/
{
	#define MAX_WITH 32
	REBCNT wlen;
	REBUNI with_chars[MAX_WITH];	// chars to be trimmed
	REBUNI *up = with_chars;
	REBYTE *bp;
	REBCNT n;
	REBUNI uc;

	// Setup WITH array from arg or the default:
	n = 0;
	if (IS_NONE(with)) {
		bp = "\n \r\t";
		wlen = n = 4;
	}
	else if (IS_CHAR(with)) {
		wlen = 1;
		*up++ = VAL_CHAR(with);
	}
	else if (IS_INTEGER(with)) {
		wlen = 1;
		*up++ = Int32s(with, 0);
	}
	else if (ANY_BINSTR(with)) {
		n = VAL_LEN(with);
		if (n >= MAX_WITH) n = MAX_WITH-1;
		wlen = n;
		if (VAL_BYTE_SIZE(with)) {
			bp = VAL_BIN_DATA(with);
		} else {
			memcpy(up, VAL_UNI_DATA(with), n * sizeof(REBUNI));
			n = 0;
		}
	}
	for (; n > 0; n--) *up++ = (REBUNI)*bp++;

	// Remove all occurances of chars found in WITH string:
	for (n = index; index < tail; index++) {
		uc = GET_ANY_CHAR(ser, index);
		if (!find_in_uni(with_chars, wlen, uc)) {
			SET_ANY_CHAR(ser, n, uc);
			n++;
		}
	}

	SET_ANY_CHAR(ser, n, 0);	
	SERIES_TAIL(ser) = n;
}
Exemple #4
0
static void swap_chars(REBVAL *val1, REBVAL *val2)
{
	REBUNI c1;
	REBUNI c2;
	REBSER *s1 = VAL_SERIES(val1);
	REBSER *s2 = VAL_SERIES(val2);

	c1 = GET_ANY_CHAR(s1, VAL_INDEX(val1));
	c2 = GET_ANY_CHAR(s2, VAL_INDEX(val2));

	if (BYTE_SIZE(s1) && c2 > 0xff) Widen_String(s1);
	SET_ANY_CHAR(s1, VAL_INDEX(val1), c2);
	
	if (BYTE_SIZE(s2) && c1 > 0xff) Widen_String(s2);
	SET_ANY_CHAR(s2, VAL_INDEX(val2), c1);
}
Exemple #5
0
//
//  Shuffle_String: C
// 
// Randomize a string. Return a new string series.
// Handles both BYTE and UNICODE strings.
//
void Shuffle_String(REBVAL *value, REBOOL secure)
{
    REBCNT n;
    REBCNT k;
    REBSER *series = VAL_SERIES(value);
    REBCNT idx     = VAL_INDEX(value);
    REBUNI swap;

    for (n = VAL_LEN_AT(value); n > 1;) {
        k = idx + (REBCNT)Random_Int(secure) % n;
        n--;
        swap = GET_ANY_CHAR(series, k);
        SET_ANY_CHAR(series, k, GET_ANY_CHAR(series, n + idx));
        SET_ANY_CHAR(series, n + idx, swap);
    }
}
Exemple #6
0
//
//  RL_Set_Char: C
// 
// Set a character into a byte or unicode string.
// 
// Returns:
//     The index passed as an argument.
// Arguments:
//     series - string series pointer
//     index - where to store the character. If past the tail,
//         the string will be auto-expanded by one and the char
//         will be appended.
//
RL_API u32 RL_Set_Char(REBSER *series, u32 index, u32 chr)
{
    if (index >= SER_LEN(series)) {
        index = SER_LEN(series);
        EXPAND_SERIES_TAIL(series, 1);
    }
    SET_ANY_CHAR(series, index, chr);
    return index;
}
Exemple #7
0
*/	REBINT PD_String(REBPVS *pvs)
/*
***********************************************************************/
{
	REBVAL *data = pvs->value;
	REBVAL *val = pvs->setval;
	REBINT n = 0;
	REBCNT i;
	REBINT c;
	REBSER *ser = VAL_SERIES(data);

	if (IS_INTEGER(pvs->select)) {
		n = Int32(pvs->select) + VAL_INDEX(data) - 1;
	}
	else return PE_BAD_SELECT;

	if (val == 0) {
		if (n < 0 || (REBCNT)n >= SERIES_TAIL(ser)) return PE_NONE;
		if (IS_BINARY(data)) {
			SET_INTEGER(pvs->store, *BIN_SKIP(ser, n));
		} else {
			SET_CHAR(pvs->store, GET_ANY_CHAR(ser, n));
		}
		return PE_USE;
	}

	if (n < 0 || (REBCNT)n >= SERIES_TAIL(ser)) return PE_BAD_RANGE;

	if (IS_CHAR(val)) {
		c = VAL_CHAR(val);
		if (c > MAX_CHAR) return PE_BAD_SET;
	}
	else if (IS_INTEGER(val)) {
		c = Int32(val);
		if (c > MAX_CHAR || c < 0) return PE_BAD_SET;
		if (IS_BINARY(data)) { // special case for binary
			if (c > 0xff) Trap_Range(val);
			BIN_HEAD(ser)[n] = (REBYTE)c;
			return PE_OK;
		}
	}
	else if (ANY_BINSTR(val)) {
		i = VAL_INDEX(val);
		if (i >= VAL_TAIL(val)) return PE_BAD_SET;
		c = GET_ANY_CHAR(VAL_SERIES(val), i);
	}
	else
		return PE_BAD_SELECT;

	TRAP_PROTECT(ser);

	if (BYTE_SIZE(ser) && c > 0xff) Widen_String(ser);
	SET_ANY_CHAR(ser, n, c);

	return PE_OK;
}
Exemple #8
0
*/	void Insert_Char(REBSER *dst, REBCNT index, REBCNT chr)
/*
**		Insert a Char (byte or unicode) into a string.
**
***********************************************************************/
{
    if (index > dst->tail) index = dst->tail;
    if (chr > 0xFF && BYTE_SIZE(dst)) Widen_String(dst, TRUE);
    Expand_Series(dst, index, 1);
    SET_ANY_CHAR(dst, index, chr);
}
Exemple #9
0
*/	void Shuffle_String(REBVAL *value, REBFLG secure)
/*
**		Randomize a string. Return a new string series.
**		Handles both BYTE and UNICODE strings.
**
***********************************************************************/
{
	REBCNT n;
	REBCNT k;
	REBSER *series = VAL_SERIES(value);
	REBCNT idx     = VAL_INDEX(value);
	REBUNI swap;

	for (n = VAL_LEN(value); n > 1;) {
		k = idx + (REBCNT)Random_Int(secure) % n;
		n--;
		swap = GET_ANY_CHAR(series, k);
		SET_ANY_CHAR(series, k, GET_ANY_CHAR(series, n + idx));
		SET_ANY_CHAR(series, n + idx, swap);
	}
}
Exemple #10
0
*/	static int Read_Dir(REBREQ *dir, REBSER *files)
/*
**		Provide option to get file info too.
**		Provide option to prepend dir path.
**		Provide option to use wildcards.
**
***********************************************************************/
{
	REBINT result;
	REBCNT len;
	REBSER *fname;
	REBSER *name;
	REBREQ file;

	RESET_TAIL(files);
	CLEARS(&file);

	// Temporary filename storage:
	fname = BUF_OS_STR;
	file.special.file.path = cast(REBCHR*, Reset_Buffer(fname, MAX_FILE_NAME));

	SET_FLAG(dir->modes, RFM_DIR);

	dir->common.data = cast(REBYTE*, &file);

	while ((result = OS_DO_DEVICE(dir, RDC_READ)) == 0 && !GET_FLAG(dir->flags, RRF_DONE)) {
		len = OS_STRLEN(file.special.file.path);
		if (GET_FLAG(file.modes, RFM_DIR)) len++;
		name = Copy_OS_Str(file.special.file.path, len);
		if (GET_FLAG(file.modes, RFM_DIR))
			SET_ANY_CHAR(name, name->tail-1, '/');
		Val_Init_File(Alloc_Tail_Array(files), name);
	}

	if (result < 0 && dir->error != -RFE_OPEN_FAIL
		&& (
			OS_STRCHR(dir->special.file.path, '*')
			|| OS_STRCHR(dir->special.file.path, '?')
		)
	) {
		result = 0;  // no matches found, but not an error
	}

	return result;
}
Exemple #11
0
RL_API u32 RL_Set_Char(REBSER *series, u32 index, u32 chr)
/*
**	Set a character into a byte or unicode string.
**
**	Returns:
**		The index passed as an argument.
**	Arguments:
**		series - string series pointer
**		index - where to store the character. If past the tail,
**			the string will be auto-expanded by one and the char
**			will be appended.
*/
{
	if (index >= series->tail) {
		index = series->tail;
		EXPAND_SERIES_TAIL(series, 1);
	}
	SET_ANY_CHAR(series, index, chr);
	return index;
}
Exemple #12
0
*/	static int Read_Dir(REBREQ *dir, REBSER *files)
/*
**		Provide option to get file info too.
**		Provide option to prepend dir path.
**		Provide option to use wildcards.
**
***********************************************************************/
{
	REBINT result;
	REBCNT len;
	REBSER *fname;
	REBSER *name;
	REBREQ file;

	RESET_TAIL(files);
	CLEARS(&file);

	// Temporary filename storage:
	fname = BUF_OS_STR;
	file.file.path = (REBCHR*)Reset_Buffer(fname, MAX_FILE_NAME);

	SET_FLAG(dir->modes, RFM_DIR);

	dir->data = (REBYTE*)(&file);

	while ((result = OS_DO_DEVICE(dir, RDC_READ)) == 0 && !GET_FLAG(dir->flags, RRF_DONE)) {
		len = LEN_STR(file.file.path);
		if (GET_FLAG(file.modes, RFM_DIR)) len++;
		name = Copy_OS_Str(file.file.path, len);
		if (GET_FLAG(file.modes, RFM_DIR))
			SET_ANY_CHAR(name, name->tail-1, '/');
		Set_Series(REB_FILE, Append_Value(files), name);
	}

	if (result < 0 && dir->error != -RFE_OPEN_FAIL
		&& (FIND_CHR(dir->file.path, '*') || FIND_CHR(dir->file.path, '?')))
		result = 0;  // no matches found, but not an error

	return result;
}
Exemple #13
0
*/	static REB_R Console_Actor(struct Reb_Call *call_, REBSER *port, REBCNT action)
/*
***********************************************************************/
{
	REBREQ *req;
	REBINT result;
	REBVAL *arg = D_ARG(2);
	REBSER *ser;

	Validate_Port(port, action);

	arg = D_ARG(2);
	*D_OUT = *D_ARG(1);

	req = cast(REBREQ*, Use_Port_State(port, RDI_STDIO, sizeof(REBREQ)));

	switch (action) {

	case A_READ:

		// If not open, open it:
		if (!IS_OPEN(req)) {
			if (OS_DO_DEVICE(req, RDC_OPEN)) Trap_Port_DEAD_END(RE_CANNOT_OPEN, port, req->error);
		}

		// If no buffer, create a buffer:
		arg = OFV(port, STD_PORT_DATA);
		if (!IS_STRING(arg) && !IS_BINARY(arg)) {
			Set_Binary(arg, MAKE_OS_BUFFER(OUT_BUF_SIZE));
		}
		ser = VAL_SERIES(arg);
		RESET_SERIES(ser);

		req->common.data = BIN_HEAD(ser);
		req->length = SERIES_AVAIL(ser);

#ifdef nono
		// Is the buffer large enough?
		req->length = SERIES_AVAIL(ser); // space available
		if (req->length < OUT_BUF_SIZE/2) Extend_Series(ser, OUT_BUF_SIZE);
		req->length = SERIES_AVAIL(ser);

		// Don't make buffer too large:  Bug #174   ?????
		if (req->length > 1024) req->length = 1024;  //???
		req->common.data = STR_TAIL(ser); // write at tail  //???
		if (SERIES_TAIL(ser) == 0) req->actual = 0;  //???
#endif

		result = OS_DO_DEVICE(req, RDC_READ);
		if (result < 0) Trap_Port_DEAD_END(RE_READ_ERROR, port, req->error);

#ifdef nono
		// Does not belong here!!
		// Remove or replace CRs:
		result = 0;
		for (n = 0; n < req->actual; n++) {
			chr = GET_ANY_CHAR(ser, n);
			if (chr == CR) {
				chr = LF;
				// Skip LF if it follows:
				if ((n+1) < req->actual &&
					LF == GET_ANY_CHAR(ser, n+1)) n++;
			}
			SET_ANY_CHAR(ser, result, chr);
			result++;
		}
#endif
		// !!! Among many confusions in this file, it said "Another copy???"
		//Set_String(D_OUT, Copy_OS_Str(ser->data, result));
		Set_Binary(D_OUT, Copy_Bytes(req->common.data, req->actual));
		break;

	case A_OPEN:
		// ?? why???
		//if (OS_DO_DEVICE(req, RDC_OPEN)) Trap_Port_DEAD_END(RE_CANNOT_OPEN, port);
		SET_OPEN(req);
		break;

	case A_CLOSE:
		SET_CLOSED(req);
		//OS_DO_DEVICE(req, RDC_CLOSE);
		break;

	case A_OPENQ:
		if (IS_OPEN(req)) return R_TRUE;
		return R_FALSE;

	default:
		Trap_Action_DEAD_END(REB_PORT, action);
	}

	return R_OUT;
}
Exemple #14
0
*/	static void trim_head_tail(REBSER *ser, REBCNT index, REBCNT tail, REBFLG h, REBFLG t)
/*
**		Trim from head and tail of each line, trim any leading or
**		trailing lines as well, leaving one at the end if present
**
***********************************************************************/
{
	REBCNT start = index;
	REBCNT out = index;
	REBUNI uc;

	// Skip head lines if required:
	if (h || !t) {
		for (; index < tail; index++) {
			uc = GET_ANY_CHAR(ser, index);
			if (!IS_WHITE(uc)) break;
		}
	}

	// Trim the head and tail parts of a line:
	if (!h && !t) {
		REBINT hf = 1; // head space flag
		REBINT tf = 0; // tail space flag and index

		// Trim lines:
		for (; index < tail; index++) {

			uc = GET_ANY_CHAR(ser, index);

			if (IS_SPACE(uc)) {
				if (hf) continue; // trim from head
				tf = index;       // tailing spaces?
			}
			else if (uc == LF) {
				hf = 1;
				if (tf) out = tf;
				tf = 0;
			}
			else
				hf = tf = 0;

			SET_ANY_CHAR(ser, out, uc);
			out++;
		}
	}
	else {
		for (; index < tail; index++) {
			uc = GET_ANY_CHAR(ser, index);
			SET_ANY_CHAR(ser, out, uc);
			out++;
		}
	}

	// Trim tail lines if required:
	if (t || !h) {
		REBOOL flag = FALSE; // found newline

		for (out--; out >= start; out--) {
			uc = GET_ANY_CHAR(ser, out);
			if (!IS_WHITE(uc)) break;
			if (uc == LF) flag = TRUE;
		}

		out++;
		if (!t && flag) {
			SET_ANY_CHAR(ser, out, LF);
			out++;
		}
	}

	SET_ANY_CHAR(ser, out, 0);
	SERIES_TAIL(ser) = out;
}