From 9e3cbaaacd01aa75622252fe42d35a47014da1fd Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 26 Sep 2018 12:16:07 +0900 Subject: Avoid using `memmove()` for performance; fix #4130 --- mrbgems/mruby-string-ext/src/string.c | 61 ++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 30 deletions(-) (limited to 'mrbgems/mruby-string-ext/src') diff --git a/mrbgems/mruby-string-ext/src/string.c b/mrbgems/mruby-string-ext/src/string.c index 3faa3d428..aedff7266 100644 --- a/mrbgems/mruby-string-ext/src/string.c +++ b/mrbgems/mruby-string-ext/src/string.c @@ -386,6 +386,7 @@ str_tr(mrb_state *mrb, mrb_value str, mrb_value p1, mrb_value p2, mrb_bool squee char *s; mrb_int len; mrb_int i; + mrb_int j; mrb_bool flag_changed = FALSE; mrb_int lastch = -1; @@ -395,21 +396,22 @@ str_tr(mrb_state *mrb, mrb_value str, mrb_value p1, mrb_value p2, mrb_bool squee s = RSTRING_PTR(str); len = RSTRING_LEN(str); - for (i = 0; i < len; i++) { + for (i=j=0; ij) s[j] = s[i]; if (n >= 0) { flag_changed = TRUE; if (rep == NULL) { - compact: - memmove(s + i, s + i + 1, len - i); - len--; - i--; + j--; } else { mrb_int c = tr_get_character(rep, n); - if (squeeze && c == lastch) goto compact; + if (squeeze && c == lastch) { + j--; + continue; + } if (c < 0 || c > 0x80) { mrb_raisef(mrb, E_ARGUMENT_ERROR, "character (%S) out of range", mrb_fixnum_value((mrb_int)c)); @@ -422,9 +424,10 @@ str_tr(mrb_state *mrb, mrb_value str, mrb_value p1, mrb_value p2, mrb_bool squee tr_free_pattern(mrb, pat); if (rep) tr_free_pattern(mrb, rep); - RSTR_SET_LEN(RSTRING(str), len); - RSTRING_PTR(str)[len] = 0; - + if (flag_changed) { + RSTR_SET_LEN(RSTRING(str), j); + RSTRING_PTR(str)[j] = 0; + } return flag_changed; } @@ -542,7 +545,7 @@ static mrb_bool str_squeeze(mrb_state *mrb, mrb_value str, mrb_value v_pat) { struct tr_pattern *pat = NULL; - mrb_int i; + mrb_int i, j; unsigned char *s; mrb_int len; mrb_bool flag_changed = FALSE; @@ -556,34 +559,33 @@ str_squeeze(mrb_state *mrb, mrb_value str, mrb_value v_pat) len = RSTRING_LEN(str); if (pat) { - for (i = 0; i < len; i++) { + for (i=j=0; ij) s[j] = s[i]; if (n >= 0 && s[i] == lastch) { flag_changed = TRUE; - memmove(s + i, s + i + 1, len - i); - len--; - i--; + j--; } lastch = s[i]; } } else { - for (i = 0; i < len; i++) { + for (i=j=0; ij) s[j] = s[i]; if (s[i] == lastch) { flag_changed = TRUE; - memmove(s + i, s + i + 1, len - i); - len--; - i--; + j--; } lastch = s[i]; } } tr_free_pattern(mrb, pat); - RSTR_SET_LEN(RSTRING(str), len); - RSTRING_PTR(str)[len] = 0; - + if (flag_changed) { + RSTR_SET_LEN(RSTRING(str), j); + RSTRING_PTR(str)[j] = 0; + } return flag_changed; } @@ -636,7 +638,7 @@ static mrb_bool str_delete(mrb_state *mrb, mrb_value str, mrb_value v_pat) { struct tr_pattern *pat = NULL; - mrb_int i; + mrb_int i, j; char *s; mrb_int len; mrb_bool flag_changed = FALSE; @@ -646,21 +648,20 @@ str_delete(mrb_state *mrb, mrb_value str, mrb_value v_pat) s = RSTRING_PTR(str); len = RSTRING_LEN(str); - for (i = 0; i < len; i++) { + for (i=j=0; ij) s[j] = s[i]; if (n >= 0) { flag_changed = TRUE; - memmove(s + i, s + i + 1, len - i); - len--; - i--; + j--; } } tr_free_pattern(mrb, pat); - - RSTR_SET_LEN(RSTRING(str), len); - RSTRING_PTR(str)[len] = 0; - + if (flag_changed) { + RSTR_SET_LEN(RSTRING(str), j); + RSTRING_PTR(str)[j] = 0; + } return flag_changed; } -- cgit v1.2.3