From 007b46bc45afb6ad4f55c1da6b4818564e238797 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Grubbstr=C3=B6m=20=28Grubba=29?= <grubba@grubba.org> Date: Sat, 11 Mar 2006 14:23:44 +0100 Subject: [PATCH] Extracted some loop-invariants in replace_many(). It's now ~82% as fast as the serial case in the benchmark (it used to be ~53%). Rev: src/builtin_functions.c:1.613 --- src/builtin_functions.c | 152 +++++++++++++++++++++------------------- 1 file changed, 78 insertions(+), 74 deletions(-) diff --git a/src/builtin_functions.c b/src/builtin_functions.c index 75c9554fef..7353f96883 100644 --- a/src/builtin_functions.c +++ b/src/builtin_functions.c @@ -2,7 +2,7 @@ || This file is part of Pike. For copyright information see COPYRIGHT. || Pike is distributed under GPL, LGPL and MPL. See the file COPYING || for more information. -|| $Id: builtin_functions.c,v 1.612 2006/03/11 12:31:35 grubba Exp $ +|| $Id: builtin_functions.c,v 1.613 2006/03/11 13:23:44 grubba Exp $ */ #include "global.h" @@ -3505,79 +3505,83 @@ static struct pike_string *replace_many(struct pike_string *str, /* FIXME: We really ought to build a trie! */ - for(e = s = 0;length > 0;) - { - INT32 a,b; - p_wchar2 ch; - - ch=index_shared_string(str,s); - if(ch<NELEM(set_end)) { - b=set_end[ch]; - if (!b) goto next_char; - a=set_start[ch]; - } else { - b=num; - a=other_start; - } - if (a >= b) goto next_char; - - { - a=find_longest_prefix(str->str+(s << str->size_shift), - length, - str->size_shift, - ctx.v, a, b); - - if(a!=-1) - { - if (s != e) { - switch(str->size_shift) { - case 0: - string_builder_binary_strcat0(&ctx.ret, STR0(str)+e, s-e); - break; - case 1: - string_builder_binary_strcat1(&ctx.ret, STR1(str)+e, s-e); - break; - case 2: - string_builder_binary_strcat2(&ctx.ret, STR2(str)+e, s-e); - break; - } - } - ch = ctx.v[a].ind->len; - s+=ch; - length-=ch; - e = s; - string_builder_shared_strcat(&ctx.ret,ctx.v[a].val); - if (empty_repl && length) { - /* Append the replacement for the empty string too. */ - string_builder_shared_strcat(&ctx.ret, empty_repl); - } - continue; - } - } - next_char: - s++; - length--; - if (empty_repl && length) { - /* We have a replace with the empty string, - * and we're not on the last character in the source string. - */ - string_builder_putchar(&ctx.ret, ch); - string_builder_shared_strcat(&ctx.ret, empty_repl); - e = s; - } - } - if (e < s) { - switch(str->size_shift) { - case 0: - string_builder_binary_strcat0(&ctx.ret, STR0(str)+e, s-e); - break; - case 1: - string_builder_binary_strcat1(&ctx.ret, STR1(str)+e, s-e); - break; - case 2: - string_builder_binary_strcat2(&ctx.ret, STR2(str)+e, s-e); - break; - } + switch (str->size_shift) { +#define CASE(SZ) \ + case (SZ): \ + { \ + PIKE_CONCAT(p_wchar, SZ) *ss = \ + PIKE_CONCAT(STR, SZ)(str); \ + for(e = s = 0;length > 0;) \ + { \ + INT32 a, b; \ + p_wchar2 ch; \ + \ + ch = ss[s]; \ + if(OPT_IS_CHAR(ch)) { \ + b=set_end[ch]; \ + if (!b) \ + goto PIKE_CONCAT(next_char, SZ); \ + a=set_start[ch]; \ + } else { \ + b=num; \ + a=other_start; \ + } \ + if (a >= b) \ + goto PIKE_CONCAT(next_char, SZ); \ + \ + a = find_longest_prefix((char *)(ss + s), \ + length, \ + SZ, \ + ctx.v, a, b); \ + \ + if(a >= 0) \ + { \ + if (s != e) { \ + PIKE_CONCAT(string_builder_binary_strcat, \ + SZ)(&ctx.ret, ss+e, s-e); \ + } \ + ch = ctx.v[a].ind->len; \ + s += ch; \ + length -= ch; \ + e = s; \ + string_builder_shared_strcat(&ctx.ret, \ + ctx.v[a].val); \ + if (empty_repl && length) { \ + /* Append the replacement for \ + * the empty string too. */ \ + string_builder_shared_strcat(&ctx.ret, \ + empty_repl); \ + } \ + continue; \ + } \ + \ + PIKE_CONCAT(next_char, SZ): \ + s++; \ + length--; \ + if (empty_repl && length) { \ + /* We have a replace with the empty string, \ + * and we're not on the last character \ + * in the source string. \ + */ \ + string_builder_putchar(&ctx.ret, ch); \ + string_builder_shared_strcat(&ctx.ret, \ + empty_repl); \ + e = s; \ + } \ + } \ + if (e < s) { \ + PIKE_CONCAT(string_builder_binary_strcat, SZ) \ + (&ctx.ret, ss+e, s-e); \ + } \ + } \ + break +#define OPT_IS_CHAR(X) 1 + CASE(0); +#undef OPT_IS_CHAR +#define OPT_IS_CHAR(X) ((X) < NELEM(set_end)) + CASE(1); + CASE(2); +#undef OPT_IS_CHAR } UNSET_ONERROR (uwp); -- GitLab