mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
string.c: implement __sub_replace() in C.
To reduce number of string allocation.
This commit is contained in:
+5
-32
@@ -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 */
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user