hare

The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

commit 82853163f0be76ca118c7efd7b02acec82a9b16d
parent ec3d6a2edcff1fcb493dfedf3f55a82982c3bb0a
Author: Sebastian <sebastian@sebsite.pw>
Date:   Tue,  1 Mar 2022 17:15:41 -0500

strings: add multireplace

Signed-off-by: Sebastian <sebastian@sebsite.pw>

Diffstat:
Mstrings/replace.ha | 41+++++++++++++++++++++++++++++------------
1 file changed, 29 insertions(+), 12 deletions(-)

diff --git a/strings/replace.ha b/strings/replace.ha @@ -7,20 +7,30 @@ use bytes; // Returns a new string duplicated from 's', but with all instances of 'needle' // replaced with 'target'. The caller must free the return value. export fn replace(s: str, needle: str, target: str) str = { + return multireplace(s, (needle, target)); +}; + +// For each tuple given by 'repls', a replacement of 's' is done like in +// [[replace]], in the order that they are passed as arguments. This function is +// nearly equivalent to calling [[replace]] multiple times, except only one new +// string is allocated. The caller must free the return value. +export fn multireplace(s: str, repls: (str, str)...) str = { let res = toutf8(dup(s)); - let needle = toutf8(needle); - let target = toutf8(target); - let match_idx = 0z; - for (true) { - match_idx = match(bytes::index(res[match_idx..], needle)) { - case let s: size => - yield match_idx + s; - case void => - break; + for (let i = 0z; i < len(repls); i += 1) { + let needle = toutf8(repls[i].0); + let target = toutf8(repls[i].1); + let idx = 0z; + for (true) { + idx = match(bytes::index(res[idx..], needle)) { + case let s: size => + yield s + idx; + case void => + break; + }; + delete(res[idx..idx + len(needle)]); + insert(res[idx], target...); + idx += len(target); }; - delete(res[match_idx..match_idx + len(needle)]); - insert(res[match_idx], target...); - match_idx += len(target); }; return fromutf8(res); }; @@ -33,3 +43,10 @@ export fn replace(s: str, needle: str, target: str) str = { assert(replace("aaa", "a", "aa") == "aaaaaa"); assert(replace("こんにちは", "にち", "ばん") == "こんばんは"); }; + +@test fn multireplace() void = { + assert(multireplace("Hello world", ("Hello", "Greetings"), + ("world", "globe")) == "Greetings globe"); + assert(multireplace("ababa", ("a", "ba"), ("b", "a"), ("a", "c")) == + "cccccccc"); +};