diff --git a/parse.y b/parse.y index 915db67..0a93ead 100644 --- a/parse.y +++ b/parse.y @@ -10311,6 +10311,17 @@ rb_intern_str(VALUE str) return intern_str(rb_str_dup(str)); } +ID +rb_interned_str(VALUE str) +{ + st_data_t id; + + if (st_lookup(global_symbols.sym_id, str, &id)) + return (ID)id; + + return (ID)0; +} + VALUE rb_id2str(ID id) { diff --git a/string.c b/string.c index 04984f0..12f7487 100644 --- a/string.c +++ b/string.c @@ -7196,6 +7196,61 @@ rb_str_intern(VALUE s) /* * call-seq: + * str.interned -> symbol + * + * Returns the Symbol corresponding to str, returning + * nil if it did not previously exist. See Symbol#id2name. + * + * x = :banana + * "banana".interned #=> :banana + * "mango".interned #=> nil + * + */ + +VALUE +rb_str_interned(VALUE s) +{ + VALUE str = RB_GC_GUARD(s); + ID id; + + id = rb_interned_str(str); + if (id == ID(0)) + return Qnil; + + return ID2SYM(id); +} + + +/* + * call-seq: + * str.to_existing_sym -> symbol + * + * Returns the Symbol corresponding to str, raising an + * ArgumentError if it did not previously exist. + * See Symbol#id2name. + * + * x = :banana + * "banana".to_existing_sym #=> :banana + * "mango".to_existing_sym #=> ArgumentError + * + */ + +VALUE +rb_str_to_existing_sym(VALUE s) +{ + VALUE str = RB_GC_GUARD(s); + ID id; + + id = rb_interned_str(str); + if (id == ID(0)) + rb_raise(rb_eArgError, "undefined symbol :'%s'", StringValuePtr(str)); + + return ID2SYM(id); +} + + +/* + * call-seq: * str.ord -> integer * * Return the Integer ordinal of a one-character string. @@ -8238,6 +8293,8 @@ Init_String(void) rb_define_method(rb_cString, "crypt", rb_str_crypt, 1); rb_define_method(rb_cString, "intern", rb_str_intern, 0); rb_define_method(rb_cString, "to_sym", rb_str_intern, 0); + rb_define_method(rb_cString, "interned", rb_str_interned, 0); + rb_define_method(rb_cString, "to_existing_sym", rb_str_interned_err, 0); rb_define_method(rb_cString, "ord", rb_str_ord, 0); rb_define_method(rb_cString, "include?", rb_str_include, 1);