// a b c // <sought> <replacement> [<start>] // <start> <length> <replacement> static inline struct variable *cfnc_replace(struct context *context) { struct variable *args = (struct variable*)stack_pop(context->operand_stack); struct variable *self = (struct variable*)array_get(args->list.ordered, 0); struct variable *a = (struct variable*)array_get(args->list.ordered, 1); struct variable *b = (struct variable*)array_get(args->list.ordered, 2); struct variable *c = args->list.ordered->length > 3 ? (struct variable*)array_get(args->list.ordered, 3) : NULL; null_check(self); null_check(b); assert_message(self->type == VAR_STR, "searching in a non-string"); struct byte_array *replaced = NULL; if (a->type == VAR_STR) { // find a, replace with b assert_message(b->type == VAR_STR, "non-string replacement"); int32_t where = 0; if (c) { // replace first match after index c assert_message(c->type == VAR_INT, "non-integer index"); if (((where = byte_array_find(self->str, a->str, c->integer)) >= 0)) replaced = byte_array_replace(self->str, b->str, where, b->str->length); } else { replaced = byte_array_replace_all(self->str, a->str, b->str); } } else if (a->type == VAR_INT ) { // replace at index a, length b, insert c assert_message(a || a->type == VAR_INT, "non-integer count"); assert_message(b || b->type == VAR_INT, "non-integer start"); replaced = byte_array_replace(self->str, c->str, a->integer, b->integer); } else exit_message("replacement is not a string"); null_check(replaced); struct variable *result = variable_new_str(context, replaced); byte_array_del(replaced); return result; }
struct byte_array *byte_array_replace_all(struct byte_array *original, struct byte_array *a, struct byte_array *b) { /*DEBUGPRINT("replace in %s: %s -> %s\n", byte_array_to_string(original), byte_array_to_string(a), byte_array_to_string(b));*/ struct byte_array *replaced = byte_array_copy(original); int32_t where = 0; for(;;) { // replace all if ((where = byte_array_find(replaced, a, where)) < 0) break; struct byte_array *replaced2 = byte_array_replace(replaced, b, where++, a->length); byte_array_del(replaced); replaced = replaced2; } return replaced; }