diff --git a/include/mruby/string.h b/include/mruby/string.h index b88259452..22683b89a 100644 --- a/include/mruby/string.h +++ b/include/mruby/string.h @@ -342,6 +342,16 @@ MRB_API const char *mrb_string_value_cstr(mrb_state *mrb, mrb_value *str); */ MRB_API mrb_value mrb_str_dup(mrb_state *mrb, mrb_value str); +/** + * Returns a frozen string object. + * The string will be duplicated and frozen if it is not already frozen. + * + * @param mrb The current mruby state. + * @param str An original Ruby string. + * @return [mrb_value] Ruby frozen string. + */ +MRB_API mrb_value mrb_str_dup_frozen(mrb_state *mrb, mrb_value str); + /** * Returns a symbol from a passed in Ruby string. * diff --git a/src/string.c b/src/string.c index d490ec310..9f886b95f 100644 --- a/src/string.c +++ b/src/string.c @@ -1358,6 +1358,16 @@ mrb_str_dup(mrb_state *mrb, mrb_value str) return str_replace(mrb, dup, s); } +MRB_API mrb_value +mrb_str_dup_frozen(mrb_state *mrb, mrb_value str) +{ + if (!mrb_frozen_p(mrb_basic_ptr(str))) { + str = mrb_str_dup(mrb, str); + mrb_basic_ptr(str)->frozen = TRUE; + } + return str; +} + enum str_convert_range { /* `beg` and `len` are byte unit in `0 ... str.bytesize` */ STR_BYTE_RANGE_CORRECTED = 1,