*/ REBSER *Prep_String(REBSER *series, REBYTE **str, REBCNT len) /* ** Helper function for the string related Mold functions below. ** Creates or expands the series and provides the location to ** copy text into. ** ***********************************************************************/ { REBCNT tail; if (!series) { series = Make_Binary(len); series->tail = len; *str = STR_HEAD(series); } else { tail = SERIES_TAIL(series); EXPAND_SERIES_TAIL(series, len); *str = STR_SKIP(series, tail); } return series; }
x*/ REBCNT Match_2_String(REBSER *series, REBCNT index, REBYTE *str, REBCNT len, REBINT uncase) /* ** (Evaluate if there is another function to use. ???!!!) ** ** Used for: PARSE function ** ***********************************************************************/ { REBYTE *ser = STR_SKIP(series, index); REBCNT tail = series->tail; if (uncase) { for (;len > 0 && index < tail; index++, len--) { if (*ser++ != *str++) return 0; } } else { for (;len > 0 && index < tail; index++, len--) { if (LO_CASE(*ser++) != LO_CASE(*str++)) return 0; } } if (len == 0) return index; return 0; }
*/ static REBCNT Parse_Next_String(REBPARSE *parse, REBCNT index, REBVAL *item, REBCNT depth) /* ** Match the next item in the string ruleset. ** ** If it matches, return the index just past it. ** Otherwise return NOT_FOUND. ** ***********************************************************************/ { // !!! THIS CODE NEEDS CLEANUP AND REWRITE BASED ON OTHER CHANGES REBSER *series = parse->series; REBSER *ser; REBCNT flags = parse->flags | AM_FIND_MATCH | AM_FIND_TAIL; int rewrite_needed; if (Trace_Level) { Trace_Value(7, item); Trace_String(8, STR_SKIP(series, index), series->tail - index); } if (IS_NONE(item)) return index; if (index >= series->tail) return NOT_FOUND; switch (VAL_TYPE(item)) { // Do we match a single character? case REB_CHAR: if (HAS_CASE(parse)) index = (VAL_CHAR(item) == GET_ANY_CHAR(series, index)) ? index+1 : NOT_FOUND; else index = (UP_CASE(VAL_CHAR(item)) == UP_CASE(GET_ANY_CHAR(series, index))) ? index+1 : NOT_FOUND; break; case REB_EMAIL: case REB_STRING: case REB_BINARY: index = Find_Str_Str(series, 0, index, SERIES_TAIL(series), 1, VAL_SERIES(item), VAL_INDEX(item), VAL_LEN(item), flags); break; // Do we match to a char set? case REB_BITSET: flags = Check_Bit(VAL_SERIES(item), GET_ANY_CHAR(series, index), !HAS_CASE(parse)); index = flags ? index + 1 : NOT_FOUND; break; /* case REB_DATATYPE: // Currently: integer! if (VAL_DATATYPE(item) == REB_INTEGER) { REBCNT begin = index; while (IS_LEX_NUMBER(*str)) str++, index++; if (begin == index) index = NOT_FOUND; } break; */ case REB_TAG: case REB_FILE: // case REB_ISSUE: // !! Can be optimized (w/o COPY) ser = Copy_Form_Value(item, 0); index = Find_Str_Str(series, 0, index, SERIES_TAIL(series), 1, ser, 0, ser->tail, flags); break; case REB_NONE: break; // Parse a sub-rule block: case REB_BLOCK: index = Parse_Rules_Loop(parse, index, VAL_BLK_DATA(item), depth); break; // Do an expression: case REB_PAREN: item = Do_Block_Value_Throw(item); // might GC // old: if (IS_ERROR(item)) Throw_Error(VAL_ERR_OBJECT(item)); index = MIN(index, series->tail); // may affect tail break; default: Trap1(RE_PARSE_RULE, item); } return index; }