Avoid using `memmove()` for performance; fix #4130

parent 87ce7401
...@@ -386,6 +386,7 @@ str_tr(mrb_state *mrb, mrb_value str, mrb_value p1, mrb_value p2, mrb_bool squee ...@@ -386,6 +386,7 @@ str_tr(mrb_state *mrb, mrb_value str, mrb_value p1, mrb_value p2, mrb_bool squee
char *s; char *s;
mrb_int len; mrb_int len;
mrb_int i; mrb_int i;
mrb_int j;
mrb_bool flag_changed = FALSE; mrb_bool flag_changed = FALSE;
mrb_int lastch = -1; 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 ...@@ -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); s = RSTRING_PTR(str);
len = RSTRING_LEN(str); len = RSTRING_LEN(str);
for (i = 0; i < len; i++) { for (i=j=0; i<len; i++,j++) {
mrb_int n = tr_find_character(pat, s[i]); mrb_int n = tr_find_character(pat, s[i]);
if (i>j) s[j] = s[i];
if (n >= 0) { if (n >= 0) {
flag_changed = TRUE; flag_changed = TRUE;
if (rep == NULL) { if (rep == NULL) {
compact: j--;
memmove(s + i, s + i + 1, len - i);
len--;
i--;
} }
else { else {
mrb_int c = tr_get_character(rep, n); 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) { if (c < 0 || c > 0x80) {
mrb_raisef(mrb, E_ARGUMENT_ERROR, "character (%S) out of range", mrb_raisef(mrb, E_ARGUMENT_ERROR, "character (%S) out of range",
mrb_fixnum_value((mrb_int)c)); 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 ...@@ -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); tr_free_pattern(mrb, pat);
if (rep) tr_free_pattern(mrb, rep); if (rep) tr_free_pattern(mrb, rep);
RSTR_SET_LEN(RSTRING(str), len); if (flag_changed) {
RSTRING_PTR(str)[len] = 0; RSTR_SET_LEN(RSTRING(str), j);
RSTRING_PTR(str)[j] = 0;
}
return flag_changed; return flag_changed;
} }
...@@ -542,7 +545,7 @@ static mrb_bool ...@@ -542,7 +545,7 @@ static mrb_bool
str_squeeze(mrb_state *mrb, mrb_value str, mrb_value v_pat) str_squeeze(mrb_state *mrb, mrb_value str, mrb_value v_pat)
{ {
struct tr_pattern *pat = NULL; struct tr_pattern *pat = NULL;
mrb_int i; mrb_int i, j;
unsigned char *s; unsigned char *s;
mrb_int len; mrb_int len;
mrb_bool flag_changed = FALSE; mrb_bool flag_changed = FALSE;
...@@ -556,34 +559,33 @@ str_squeeze(mrb_state *mrb, mrb_value str, mrb_value v_pat) ...@@ -556,34 +559,33 @@ str_squeeze(mrb_state *mrb, mrb_value str, mrb_value v_pat)
len = RSTRING_LEN(str); len = RSTRING_LEN(str);
if (pat) { if (pat) {
for (i = 0; i < len; i++) { for (i=j=0; i<len; i++,j++) {
mrb_int n = tr_find_character(pat, s[i]); mrb_int n = tr_find_character(pat, s[i]);
if (i>j) s[j] = s[i];
if (n >= 0 && s[i] == lastch) { if (n >= 0 && s[i] == lastch) {
flag_changed = TRUE; flag_changed = TRUE;
memmove(s + i, s + i + 1, len - i); j--;
len--;
i--;
} }
lastch = s[i]; lastch = s[i];
} }
} }
else { else {
for (i = 0; i < len; i++) { for (i=j=0; i<len; i++,j++) {
if (i>j) s[j] = s[i];
if (s[i] == lastch) { if (s[i] == lastch) {
flag_changed = TRUE; flag_changed = TRUE;
memmove(s + i, s + i + 1, len - i); j--;
len--;
i--;
} }
lastch = s[i]; lastch = s[i];
} }
} }
tr_free_pattern(mrb, pat); tr_free_pattern(mrb, pat);
RSTR_SET_LEN(RSTRING(str), len); if (flag_changed) {
RSTRING_PTR(str)[len] = 0; RSTR_SET_LEN(RSTRING(str), j);
RSTRING_PTR(str)[j] = 0;
}
return flag_changed; return flag_changed;
} }
...@@ -636,7 +638,7 @@ static mrb_bool ...@@ -636,7 +638,7 @@ static mrb_bool
str_delete(mrb_state *mrb, mrb_value str, mrb_value v_pat) str_delete(mrb_state *mrb, mrb_value str, mrb_value v_pat)
{ {
struct tr_pattern *pat = NULL; struct tr_pattern *pat = NULL;
mrb_int i; mrb_int i, j;
char *s; char *s;
mrb_int len; mrb_int len;
mrb_bool flag_changed = FALSE; mrb_bool flag_changed = FALSE;
...@@ -646,21 +648,20 @@ str_delete(mrb_state *mrb, mrb_value str, mrb_value v_pat) ...@@ -646,21 +648,20 @@ str_delete(mrb_state *mrb, mrb_value str, mrb_value v_pat)
s = RSTRING_PTR(str); s = RSTRING_PTR(str);
len = RSTRING_LEN(str); len = RSTRING_LEN(str);
for (i = 0; i < len; i++) { for (i=j=0; i<len; i++,j++) {
mrb_int n = tr_find_character(pat, s[i]); mrb_int n = tr_find_character(pat, s[i]);
if (i>j) s[j] = s[i];
if (n >= 0) { if (n >= 0) {
flag_changed = TRUE; flag_changed = TRUE;
memmove(s + i, s + i + 1, len - i); j--;
len--;
i--;
} }
} }
tr_free_pattern(mrb, pat); tr_free_pattern(mrb, pat);
if (flag_changed) {
RSTR_SET_LEN(RSTRING(str), len); RSTR_SET_LEN(RSTRING(str), j);
RSTRING_PTR(str)[len] = 0; RSTRING_PTR(str)[j] = 0;
}
return flag_changed; return flag_changed;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment