Ejemplo n.º 1
0
*/	REBINT Compare_String_Vals(REBVAL *v1, REBVAL *v2, REBOOL uncase)
/*
**		Compare two string values. Either can be byte or unicode wide.
**
**		Uncase: compare is case-insensitive.
**
**		Used for: general string comparions (various places)
**
***********************************************************************/
{
	REBCNT l1  = VAL_LEN(v1);
	REBCNT l2  = VAL_LEN(v2);
	REBCNT len = MIN(l1, l2);
	REBINT n;

	if (IS_BINARY(v1) || IS_BINARY(v2)) uncase = FALSE;

	if (VAL_BYTE_SIZE(v1)) { // v1 is 8
		if (VAL_BYTE_SIZE(v2))
			n = Compare_Bytes(VAL_BIN_DATA(v1), VAL_BIN_DATA(v2), len, uncase);
		else
			n = -Compare_Uni_Byte(VAL_UNI_DATA(v2), VAL_BIN_DATA(v1), len, uncase);
	}
	else { // v1 is 16
		if (VAL_BYTE_SIZE(v2))
			n = Compare_Uni_Byte(VAL_UNI_DATA(v1), VAL_BIN_DATA(v2), len, uncase);
		else
			n = Compare_Uni_Str(VAL_UNI_DATA(v1), VAL_UNI_DATA(v2), len, uncase);
	}

	if (n != 0) return n;
	return l1 - l2;
}
Ejemplo n.º 2
0
*/	static To_Thru(REBPARSE *parse, REBCNT index, REBVAL *block, REBFLG is_thru)
/*
***********************************************************************/
{
	REBSER *series = parse->series;
	REBCNT type = parse->type;
	REBVAL *blk;
	REBVAL *item;
	REBCNT cmd;
	REBCNT i;
	REBCNT len;

	for (; index <= series->tail; index++) {

		for (blk = VAL_BLK(block); NOT_END(blk); blk++) {

			item = blk;

			// Deal with words and commands
			if (IS_WORD(item)) {
				if (cmd = VAL_CMD(item)) {
					if (cmd == SYM_END) {
						if (index >= series->tail) {
							index = series->tail;
							goto found;
						}
						goto next;
					}
					else if (cmd == SYM_QUOTE) {
						item = ++blk; // next item is the quoted value
						if (IS_END(item)) goto bad_target;
						if (IS_PAREN(item)) {
							item = Do_Block_Value_Throw(item); // might GC
						}

					}
					else goto bad_target;
				}
				else {
					item = Get_Var(item);
				}
			}
			else if (IS_PATH(item)) {
				item = Get_Parse_Value(item);
			}

			// Try to match it:
			if (type >= REB_BLOCK) {
				if (ANY_BLOCK(item)) goto bad_target;
				i = Parse_Next_Block(parse, index, item, 0);
				if (i != NOT_FOUND) {
					if (!is_thru) i--;
					index = i;
					goto found;
				}
			}
			else if (type == REB_BINARY) {
				REBYTE ch1 = *BIN_SKIP(series, index);

				// Handle special string types:
				if (IS_CHAR(item)) {
					if (VAL_CHAR(item) > 0xff) goto bad_target;
					if (ch1 == VAL_CHAR(item)) goto found1;
				}
				else if (IS_BINARY(item)) {
					if (ch1 == *VAL_BIN_DATA(item)) {
						len = VAL_LEN(item);
						if (len == 1) goto found1;
						if (0 == Compare_Bytes(BIN_SKIP(series, index), VAL_BIN_DATA(item), len, 0)) {
							if (is_thru) index += len;
							goto found;
						}
					}
				}
				else if (IS_INTEGER(item)) {
					if (VAL_INT64(item) > 0xff) goto bad_target;
					if (ch1 == VAL_INT32(item)) goto found1;
				}
				else goto bad_target;
			}
			else { // String
				REBCNT ch1 = GET_ANY_CHAR(series, index);
				REBCNT ch2;

				if (!HAS_CASE(parse)) ch1 = UP_CASE(ch1);

				// Handle special string types:
				if (IS_CHAR(item)) {
					ch2 = VAL_CHAR(item);
					if (!HAS_CASE(parse)) ch2 = UP_CASE(ch2);
					if (ch1 == ch2) goto found1;
				}
				else if (ANY_STR(item)) {
					ch2 = VAL_ANY_CHAR(item);
					if (!HAS_CASE(parse)) ch2 = UP_CASE(ch2);
					if (ch1 == ch2) {
						len = VAL_LEN(item);
						if (len == 1) goto found1;
						i = Find_Str_Str(series, 0, index, SERIES_TAIL(series), 1, VAL_SERIES(item), VAL_INDEX(item), len, AM_FIND_MATCH | parse->flags);
						if (i != NOT_FOUND) {
							if (is_thru) i += len;
							index = i;
							goto found;
						}
					}
				}
				else if (IS_INTEGER(item)) {
					ch1 = GET_ANY_CHAR(series, index);  // No casing!
					if (ch1 == (REBCNT)VAL_INT32(item)) goto found1;
				}
				else goto bad_target;
			}

next:		// Check for | (required if not end)
			blk++;
			if (IS_PAREN(blk)) blk++;
			if (IS_END(blk)) break;
			if (!IS_OR_BAR(blk)) {
				item = blk;
				goto bad_target;
			}
		}
	}
	return NOT_FOUND;

found:
	if (IS_PAREN(blk+1)) Do_Block_Value_Throw(blk+1);
	return index;

found1:
	if (IS_PAREN(blk+1)) Do_Block_Value_Throw(blk+1);
	return index + (is_thru ? 1 : 0);

bad_target:
	Trap1(RE_PARSE_RULE, item);
	return 0;
}