trim.ha (4194B)
1 // SPDX-License-Identifier: MPL-2.0 2 // (c) Hare authors <https://harelang.org> 3 4 use bytes; 5 6 const whitespace: [_]u8 = [' ', '\n', '\t', '\r']; 7 8 // Returns a string (borrowed from given input string) after trimming off of 9 // the start of the input string the characters in the given list of runes. If 10 // no runes are given, returns the string with leading whitespace stripped off. 11 export fn ltrim(input: str, trim: rune...) str = { 12 if (len(trim) == 0) { 13 let input = toutf8(input); 14 return fromutf8_unsafe(bytes::ltrim(input, whitespace...)); 15 }; 16 let it = iter(input); 17 for :outer (let r => next(&it)) { 18 for (let tr .. trim) { 19 if (r == tr) { 20 continue :outer; 21 }; 22 }; 23 prev(&it); 24 break; 25 }; 26 return fromutf8_unsafe(it.dec.src[it.dec.offs..]); 27 }; 28 29 // Returns a string (borrowed from given input string) after trimming off of 30 // the end of the input string the characters in the given list of runes. If no 31 // runes are given, returns the string with trailing whitespace stripped off. 32 export fn rtrim(input: str, trim: rune...) str = { 33 if (len(trim) == 0) { 34 let input = toutf8(input); 35 return fromutf8_unsafe(bytes::rtrim(input, whitespace...)); 36 }; 37 let it = riter(input); 38 for :outer (let r => next(&it)) { 39 for (let tr .. trim) { 40 if (r == tr) { 41 continue :outer; 42 }; 43 }; 44 prev(&it); 45 break; 46 }; 47 return fromutf8_unsafe(it.dec.src[..it.dec.offs]); 48 }; 49 50 // Returns a string (borrowed from given input string) after trimming off of 51 // the both ends of the input string the characters in the given list of runes. 52 // If no runes are given, returns the string with both leading and trailing 53 // whitespace stripped off. 54 export fn trim(input: str, exclude: rune...) str = 55 ltrim(rtrim(input, exclude...), exclude...); 56 57 // Returns a string (borrowed from given input string) after trimming off the 58 // given prefix. If the input string doesn't have the given prefix, it is 59 // returned unmodified. 60 export fn trimprefix(input: str, trim: str) str = { 61 if (!hasprefix(input, trim)) return input; 62 const slice = toutf8(input); 63 return fromutf8_unsafe(slice[len(trim)..]); 64 }; 65 66 // Returns a string (borrowed from given input string) after trimming off the 67 // given suffix. If the input string doesn't have the given suffix, it is 68 // returned unmodified. 69 export fn trimsuffix(input: str, trim: str) str = { 70 if (!hassuffix(input, trim)) return input; 71 const slice = toutf8(input); 72 return fromutf8_unsafe(slice[..len(input) - len(trim)]); 73 }; 74 75 @test fn trim() void = { 76 assert(ltrim("") == ""); 77 assert(ltrim(" hi") == "hi"); 78 assert(ltrim("\t\r\n hello") == "hello"); 79 assert(ltrim("((()(())))())", '(', ')') == ""); 80 assert(ltrim("abacadabra", 'a', 'b', 'c', 'd') == "ra"); 81 assert(ltrim("𝚊𝚋𝚊𝚌𝚊𝚍𝚊𝚋𝚛𝚊", '𝚊', '𝚋', '𝚌', '𝚍') == "𝚛𝚊"); // '𝚊' = U+1D68A 82 83 assert(rtrim("") == ""); 84 assert(rtrim("hello ") == "hello"); 85 assert(rtrim("hello, world\r\n\r\n") == "hello, world"); 86 assert(rtrim("Sentimentalized sensationalism sensationalized sentimentalisms", 87 ' ', 's', 'i', 'l', 'z', 't', 'm', 'n', 'o', 'e', 'a', 'd') == "S"); 88 assert(rtrim("\\/\\/\\\\//\\//\\////\\/\\", '/', '\\') == ""); 89 assert(rtrim("yellowwooddoor", 'w', 'd', 'o', 'r') == "yell"); 90 91 assert(trim("") == ""); 92 assert(trim(" ") == ""); 93 assert(trim("mississippi", 'm', 'i', 'p', 's') == ""); 94 assert(trim("[[][[[]]][][].[[]][]]][]]]", '[', ']') == "."); 95 assert(trim("AAAΑА𝖠AAAA", 'A') == "ΑА𝖠"); 96 assert(trim(" চিত্ত যেথা ভয়শূন্য, উচ্চ যেথা শির ") == "চিত্ত যেথা ভয়শূন্য, উচ্চ যেথা শির"); 97 assert(trim("𝖺𝖻𝖺𝖼𝖺𝖽𝖺𝖻𝗋𝖺𝖼𝖺𝖽𝖺𝖻𝖼𝖺", '𝖺', '𝖻', '𝖼', '𝖽') == "𝗋"); 98 99 assert(trimprefix("", "") == ""); 100 assert(trimprefix("", "blablabla") == ""); 101 assert(trimprefix("hello, world", "hello") == ", world"); 102 assert(trimprefix("blablabla", "bla") == "blabla"); 103 104 assert(trimsuffix("", "") == ""); 105 assert(trimsuffix("", "blablabla") == ""); 106 assert(trimsuffix("hello, world", "world") == "hello, "); 107 assert(trimsuffix("blablabla", "bla") == "blabla"); 108 };