diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2021-10-09 03:52:04 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2021-10-09 03:52:04 +0200 |
commit | 49bcf9f40cff1320a761d674cf89a0c0ab97ef49 (patch) | |
tree | c687441c2bf142649e8010b44e3192aadae4e47a | |
parent | 5aaeb550b76f063ffddef8587d9d91f7fddc4406 (diff) |
hush: speed up ${x//\*/|} too
function old new delta
expand_one_var 2502 2544 +42
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | shell/hush.c | 13 |
1 files changed, 9 insertions, 4 deletions
diff --git a/shell/hush.c b/shell/hush.c index 6d472337f..87fc2f445 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -6472,16 +6472,21 @@ static arith_t expand_and_evaluate_arith(const char *arg, const char **errmsg_p) /* ${var/[/]pattern[/repl]} helpers */ static char *strstr_pattern(char *val, const char *pattern, int *size) { - int sz = strcspn(pattern, "*?[\\"); - if (pattern[sz] == '\0') { + int first_escaped = (pattern[0] == '\\' && pattern[1]); + /* "first_escaped" trick allows to treat e.g. "\*no_glob_chars" + * as literal too (as it is semi-common, and easy to accomodate + * by just using str + 1). + */ + int sz = strcspn(pattern + first_escaped * 2, "*?[\\"); + if ((pattern + first_escaped * 2)[sz] == '\0') { /* Optimization for trivial patterns. * Testcase for very slow replace (performs about 22k replaces): * x=:::::::::::::::::::::: * x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;echo ${#x} * echo "${x//:/|}" */ - *size = sz; - return strstr(val, pattern); + *size = sz + first_escaped; + return strstr(val, pattern + first_escaped); } while (1) { |