From 332d8d2a1c12b098b28f8d06d2ed4bce42b09696 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Tue, 17 Oct 2017 09:59:47 +0900 Subject: Add `String#delete_{prefix,suffix}`; CRuby2.5 --- mrbgems/mruby-string-ext/src/string.c | 120 +++++++++++++++++++++++++++++++++- 1 file changed, 118 insertions(+), 2 deletions(-) (limited to 'mrbgems/mruby-string-ext/src/string.c') diff --git a/mrbgems/mruby-string-ext/src/string.c b/mrbgems/mruby-string-ext/src/string.c index 63f181749..612fc5335 100644 --- a/mrbgems/mruby-string-ext/src/string.c +++ b/mrbgems/mruby-string-ext/src/string.c @@ -650,6 +650,118 @@ mrb_str_upto(mrb_state *mrb, mrb_value beg) return beg; } +/* + * call-seq: + * str.delete_prefix!(prefix) -> self or nil + * + * Deletes leading prefix from str, returning + * nil if no change was made. + * + * "hello".delete_prefix!("hel") #=> "lo" + * "hello".delete_prefix!("llo") #=> nil + */ +static mrb_value +mrb_str_del_prefix_bang(mrb_state *mrb, mrb_value self) +{ + mrb_int plen, slen; + char *ptr, *s; + struct RString *str = RSTRING(self); + + mrb_get_args(mrb, "s", &ptr, &plen); + slen = RSTR_LEN(str); + if (plen > slen) return mrb_nil_value(); + s = RSTR_PTR(str); + if (memcmp(s, ptr, plen) != 0) return mrb_nil_value(); + if (!MRB_FROZEN_P(str) && (RSTR_SHARED_P(str) || RSTR_FSHARED_P(str))) { + str->as.heap.ptr += plen; + } + else { + mrb_str_modify(mrb, str); + s = RSTR_PTR(str); + memmove(s, s+plen, slen-plen); + } + RSTR_SET_LEN(str, slen-plen); + return self; +} + +/* + * call-seq: + * str.delete_prefix(prefix) -> new_str + * + * Returns a copy of str with leading prefix deleted. + * + * "hello".delete_prefix("hel") #=> "lo" + * "hello".delete_prefix("llo") #=> "hello" + */ +static mrb_value +mrb_str_del_prefix(mrb_state *mrb, mrb_value self) +{ + mrb_int plen, slen; + char *ptr; + + mrb_get_args(mrb, "s", &ptr, &plen); + slen = RSTRING_LEN(self); + if (plen > slen) return mrb_str_dup(mrb, self); + if (memcmp(RSTRING_PTR(self), ptr, plen) != 0) + return mrb_str_dup(mrb, self); + return mrb_str_substr(mrb, self, plen, slen-plen); +} + +/* + * call-seq: + * str.delete_suffix!(suffix) -> self or nil + * + * Deletes trailing suffix from str, returning + * nil if no change was made. + * + * "hello".delete_suffix!("llo") #=> "he" + * "hello".delete_suffix!("hel") #=> nil + */ +static mrb_value +mrb_str_del_suffix_bang(mrb_state *mrb, mrb_value self) +{ + mrb_int plen, slen; + char *ptr, *s; + struct RString *str = RSTRING(self); + + mrb_get_args(mrb, "s", &ptr, &plen); + slen = RSTR_LEN(str); + if (plen > slen) return mrb_nil_value(); + s = RSTR_PTR(str); + if (memcmp(s+slen-plen, ptr, plen) != 0) return mrb_nil_value(); + if (!MRB_FROZEN_P(str) && (RSTR_SHARED_P(str) || RSTR_FSHARED_P(str))) { + /* no need to modify string */ + } + else { + mrb_str_modify(mrb, str); + } + RSTR_SET_LEN(str, slen-plen); + return self; +} + +/* + * call-seq: + * str.delete_suffix(suffix) -> new_str + * + * Returns a copy of str with leading suffix deleted. + * + * "hello".delete_suffix("hel") #=> "lo" + * "hello".delete_suffix("llo") #=> "hello" + */ +static mrb_value +mrb_str_del_suffix(mrb_state *mrb, mrb_value self) +{ + mrb_int plen, slen; + char *ptr; + + mrb_get_args(mrb, "s", &ptr, &plen); + slen = RSTRING_LEN(self); + if (plen > slen) return mrb_str_dup(mrb, self); + if (memcmp(RSTRING_PTR(self)+slen-plen, ptr, plen) != 0) + return mrb_str_dup(mrb, self); + return mrb_str_substr(mrb, self, 0, slen-plen); +} + void mrb_mruby_string_ext_gem_init(mrb_state* mrb) { @@ -673,8 +785,12 @@ mrb_mruby_string_ext_gem_init(mrb_state* mrb) mrb_define_method(mrb, s, "succ!", mrb_str_succ_bang, MRB_ARGS_NONE()); mrb_alias_method(mrb, s, mrb_intern_lit(mrb, "next"), mrb_intern_lit(mrb, "succ")); mrb_alias_method(mrb, s, mrb_intern_lit(mrb, "next!"), mrb_intern_lit(mrb, "succ!")); - mrb_define_method(mrb, s, "ord", mrb_str_ord, MRB_ARGS_NONE()); - mrb_define_method(mrb, s, "upto", mrb_str_upto, MRB_ARGS_ANY()); + mrb_define_method(mrb, s, "ord", mrb_str_ord, MRB_ARGS_NONE()); + mrb_define_method(mrb, s, "upto", mrb_str_upto, MRB_ARGS_ANY()); + mrb_define_method(mrb, s, "delete_prefix!", mrb_str_del_prefix_bang, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, s, "delete_prefix", mrb_str_del_prefix, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, s, "delete_suffix!", mrb_str_del_suffix_bang, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, s, "delete_suffix", mrb_str_del_suffix, MRB_ARGS_REQ(1)); mrb_define_method(mrb, mrb->fixnum_class, "chr", mrb_fixnum_chr, MRB_ARGS_NONE()); } -- cgit v1.2.3 From 3c20c96f840d40950f4da61bd93f773a83767aef Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Tue, 17 Oct 2017 15:23:32 +0900 Subject: Use a new function: `mrb_get_argc()`; ref #3826 --- mrbgems/mruby-array-ext/src/array.c | 8 +++++--- mrbgems/mruby-string-ext/src/string.c | 7 ++++--- 2 files changed, 9 insertions(+), 6 deletions(-) (limited to 'mrbgems/mruby-string-ext/src/string.c') diff --git a/mrbgems/mruby-array-ext/src/array.c b/mrbgems/mruby-array-ext/src/array.c index e99599b09..169f968f9 100644 --- a/mrbgems/mruby-array-ext/src/array.c +++ b/mrbgems/mruby-array-ext/src/array.c @@ -176,14 +176,16 @@ mrb_ary_slice_bang(mrb_state *mrb, mrb_value self) { struct RArray *a = mrb_ary_ptr(self); mrb_int i, j, k, len, alen = ARY_LEN(a); - mrb_value index; mrb_value val; mrb_value *ptr; mrb_value ary; mrb_ary_modify(mrb, a); - if (mrb_get_args(mrb, "o|i", &index, &len) == 1) { + if (mrb_get_argc(mrb) == 1) { + mrb_value index; + + mrb_get_args(mrb, "o|i", &index, &len); switch (mrb_type(index)) { case MRB_TT_RANGE: if (mrb_range_beg_len(mrb, index, &i, &len, alen, TRUE) == 1) { @@ -201,7 +203,7 @@ mrb_ary_slice_bang(mrb_state *mrb, mrb_value self) } } - i = mrb_fixnum(index); + mrb_get_args(mrb, "ii", &i, &len); delete_pos_len: if (i < 0) i += alen; if (i < 0 || alen < i) return mrb_nil_value(); diff --git a/mrbgems/mruby-string-ext/src/string.c b/mrbgems/mruby-string-ext/src/string.c index 612fc5335..5195a7ba0 100644 --- a/mrbgems/mruby-string-ext/src/string.c +++ b/mrbgems/mruby-string-ext/src/string.c @@ -44,12 +44,13 @@ mrb_str_byteslice(mrb_state *mrb, mrb_value str) { mrb_value a1; mrb_int len; - mrb_int argc; - argc = mrb_get_args(mrb, "o|i", &a1, &len); - if (argc == 2) { + if (mrb_get_argc(mrb) == 2) { + mrb_int pos; + mrb_get_args(mrb, "ii", &pos, &len); return mrb_str_substr(mrb, str, mrb_fixnum(a1), len); } + mrb_get_args(mrb, "o|i", &a1, &len); switch (mrb_type(a1)) { case MRB_TT_RANGE: { -- cgit v1.2.3