string.c: implement `__sub_replace()` in C.

To reduce number of string allocation.
parent 2c41739b
......@@ -42,32 +42,6 @@ class String
self
end
# private method for gsub/sub
def __sub_replace(rep, pre, m, post)
s = ""
i = 0
while j = rep.index("\\", i)
break if j == rep.length-1
t = case rep[j+1]
when "\\"
"\\"
when "`"
pre
when "&", "0"
m
when "'"
post
when "1", "2", "3", "4", "5", "6", "7", "8", "9"
""
else
rep[j, 2]
end
s += rep[i, j-i] + t
i = j + 2
end
s + rep[i, rep.length-i]
end
##
# Replace all matches of +pattern+ with +replacement+.
# Call block (if given) for each match and replace
......@@ -92,7 +66,7 @@ class String
result << if block
block.call(pattern).to_s
else
__sub_replace(replace, self[0, found], pattern, self[offset..-1] || "")
self.__sub_replace(replace, pattern, found)
end
if plen == 0
result << self[offset, 1]
......@@ -145,17 +119,16 @@ class String
block = nil
end
result = []
this = dup
found = index(pattern)
return this unless found
result << this[0, found]
return self.dup unless found
result << self[0, found]
offset = found + pattern.length
result << if block
block.call(pattern).to_s
else
__sub_replace(replace, this[0, found], pattern, this[offset..-1] || "")
self.__sub_replace(replace, pattern, found)
end
result << this[offset..-1] if offset < length
result << self[offset..-1] if offset < length
result.join
end
......
......@@ -2847,6 +2847,51 @@ mrb_str_byteslice(mrb_state *mrb, mrb_value str)
}
}
static mrb_value
sub_replace(mrb_state *mrb, mrb_value self)
{
char *p, *match;
mrb_int plen, mlen;
mrb_int found, offset;
mrb_value result;
mrb_get_args(mrb, "ssi", &p, &plen, &match, &mlen, &found);
result = mrb_str_new(mrb, 0, 0);
for (mrb_int i=0; i<plen; i++) {
if (p[i] != '\\' || i+1==plen) {
mrb_str_cat(mrb, result, p+i, 1);
continue;
}
i++;
switch (p[i]) {
case '\\':
mrb_str_cat(mrb, result, "\\", 1);
break;
case '`':
mrb_str_cat(mrb, result, RSTRING_PTR(self), found);
break;
case '&': case '0':
mrb_str_cat(mrb, result, match, mlen);
break;
case '\'':
offset = found + mlen;
if (RSTRING_LEN(self) > offset) {
mrb_str_cat(mrb, result, RSTRING_PTR(self)+offset, RSTRING_LEN(self)-offset);
}
break;
case '1': case '2': case '3':
case '4': case '5': case '6':
case '7': case '8': case '9':
/* ignore sub-group match (no Regexp supported) */
break;
default:
mrb_str_cat(mrb, result, &p[i-1], 2);
break;
}
}
return result;
}
/* ---------------------------*/
void
mrb_init_string(mrb_state *mrb)
......@@ -2908,4 +2953,6 @@ mrb_init_string(mrb_state *mrb)
mrb_define_method(mrb, s, "getbyte", mrb_str_getbyte, MRB_ARGS_REQ(1));
mrb_define_method(mrb, s, "setbyte", mrb_str_setbyte, MRB_ARGS_REQ(2));
mrb_define_method(mrb, s, "byteslice", mrb_str_byteslice, MRB_ARGS_ARG(1,1));
mrb_define_method(mrb, s, "__sub_replace", sub_replace, MRB_ARGS_REQ(3)); /* internal */
}
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