diff options
| author | Yukihiro "Matz" Matsumoto <[email protected]> | 2021-08-31 13:00:15 +0900 |
|---|---|---|
| committer | Yukihiro "Matz" Matsumoto <[email protected]> | 2021-09-01 07:00:55 +0900 |
| commit | 3622f2c4b51d4b1f9eb0a2470ea7cd2ee24fe3a5 (patch) | |
| tree | 257435cdb71a3431e77df7620a04a77007d3cda1 /src/string.c | |
| parent | 2c41739b66e34ee20f614e4793dfb1dba4fd7274 (diff) | |
| download | mruby-3622f2c4b51d4b1f9eb0a2470ea7cd2ee24fe3a5.tar.gz mruby-3622f2c4b51d4b1f9eb0a2470ea7cd2ee24fe3a5.zip | |
string.c: implement `__sub_replace()` in C.
To reduce number of string allocation.
Diffstat (limited to 'src/string.c')
| -rw-r--r-- | src/string.c | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/src/string.c b/src/string.c index b9cc2485f..21be97db6 100644 --- a/src/string.c +++ b/src/string.c @@ -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 */ } |
